Merge pull request #413 from andyzhangx/fix-text-lib
cleanup: remove golang.org/x/text version dependency
This commit is contained in:
commit
26b1a8d66a
22
go.mod
22
go.mod
@ -10,7 +10,7 @@ require (
|
|||||||
github.com/onsi/gomega v1.10.1
|
github.com/onsi/gomega v1.10.1
|
||||||
github.com/pborman/uuid v1.2.0
|
github.com/pborman/uuid v1.2.0
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.0
|
||||||
golang.org/x/net v0.5.0
|
golang.org/x/net v0.6.0
|
||||||
google.golang.org/grpc v1.40.0
|
google.golang.org/grpc v1.40.0
|
||||||
k8s.io/api v0.23.3
|
k8s.io/api v0.23.3
|
||||||
k8s.io/apimachinery v0.23.3
|
k8s.io/apimachinery v0.23.3
|
||||||
@ -25,11 +25,12 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/aws/aws-sdk-go v1.38.49 // indirect
|
github.com/aws/aws-sdk-go v1.38.49 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
|
github.com/bits-and-blooms/bitset v1.2.0 // indirect
|
||||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
||||||
github.com/cyphar/filepath-securejoin v0.2.3 // indirect
|
github.com/cyphar/filepath-securejoin v0.2.2 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/docker/distribution v2.8.1+incompatible // indirect
|
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||||
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||||
@ -52,11 +53,11 @@ require (
|
|||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/nxadm/tail v1.4.4 // indirect
|
github.com/nxadm/tail v1.4.4 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/runc v1.1.2 // indirect
|
github.com/opencontainers/runc v1.0.2 // indirect
|
||||||
github.com/opencontainers/selinux v1.10.0 // indirect
|
github.com/opencontainers/selinux v1.8.2 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_golang v1.11.1 // indirect
|
github.com/prometheus/client_golang v1.11.0 // indirect
|
||||||
github.com/prometheus/client_model v0.2.0 // indirect
|
github.com/prometheus/client_model v0.2.0 // indirect
|
||||||
github.com/prometheus/common v0.28.0 // indirect
|
github.com/prometheus/common v0.28.0 // indirect
|
||||||
github.com/prometheus/procfs v0.6.0 // indirect
|
github.com/prometheus/procfs v0.6.0 // indirect
|
||||||
@ -72,11 +73,11 @@ require (
|
|||||||
go.opentelemetry.io/otel/sdk/metric v0.20.0 // indirect
|
go.opentelemetry.io/otel/sdk/metric v0.20.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v0.20.0 // indirect
|
go.opentelemetry.io/otel/trace v0.20.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v0.7.0 // indirect
|
go.opentelemetry.io/proto/otlp v0.7.0 // indirect
|
||||||
golang.org/x/crypto v0.5.0 // indirect
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect
|
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect
|
||||||
golang.org/x/sys v0.4.0 // indirect
|
golang.org/x/sys v0.5.0 // indirect
|
||||||
golang.org/x/term v0.4.0 // indirect
|
golang.org/x/term v0.5.0 // indirect
|
||||||
golang.org/x/text v0.6.0 // indirect
|
golang.org/x/text v0.7.0 // indirect
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
@ -99,7 +100,6 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
replace (
|
replace (
|
||||||
golang.org/x/text => golang.org/x/text v0.3.8
|
|
||||||
k8s.io/api => k8s.io/api v0.23.3
|
k8s.io/api => k8s.io/api v0.23.3
|
||||||
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.23.3
|
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.23.3
|
||||||
k8s.io/apimachinery => k8s.io/apimachinery v0.23.3
|
k8s.io/apimachinery => k8s.io/apimachinery v0.23.3
|
||||||
|
|||||||
62
go.sum
62
go.sum
@ -91,6 +91,7 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
|
|||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
|
github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA=
|
||||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||||
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
||||||
@ -106,13 +107,11 @@ github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+
|
|||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
|
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
|
||||||
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
|
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
|
||||||
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
|
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||||
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||||
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
|
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313/go.mod h1:P1wt9Z3DP8O6W3rvwCt0REIlshg1InHImaLW0t3ObY0=
|
github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313/go.mod h1:P1wt9Z3DP8O6W3rvwCt0REIlshg1InHImaLW0t3ObY0=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
@ -128,7 +127,6 @@ github.com/container-storage-interface/spec v1.5.0/go.mod h1:8K96oQNkJ7pFcC2R9Z1
|
|||||||
github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
|
github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
|
||||||
github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
|
github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
|
||||||
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
|
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
|
||||||
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
|
||||||
github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/containerd v1.4.11/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.4.11/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
|
github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
|
||||||
@ -153,9 +151,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
|
|||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
|
github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg=
|
||||||
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
||||||
github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
|
|
||||||
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@ -163,9 +160,8 @@ github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1
|
|||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||||
|
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
|
|
||||||
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
|
||||||
github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
@ -230,7 +226,6 @@ github.com/go-ozzo/ozzo-validation v3.5.0+incompatible/go.mod h1:gsEKFIVnabGBt6m
|
|||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
@ -435,7 +430,6 @@ github.com/moby/ipvs v1.0.1/go.mod h1:2pngiyseZbIKXNv7hsKj3O9UEz30c53MT9005gt2hx
|
|||||||
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
||||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||||
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
||||||
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
|
|
||||||
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
|
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
|
||||||
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
||||||
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
|
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
|
||||||
@ -475,15 +469,13 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
|
|||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
|
github.com/opencontainers/runc v1.0.2 h1:opHZMaswlyxz1OuGpBE53Dwe4/xF7EZTY0A2L/FpCOg=
|
||||||
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||||
github.com/opencontainers/runc v1.1.2 h1:2VSZwLx5k/BfsBxMMipG/LYUnmqOD/BPkIVgQUcTlLw=
|
|
||||||
github.com/opencontainers/runc v1.1.2/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
|
|
||||||
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
|
github.com/opencontainers/selinux v1.8.2 h1:c4ca10UMgRcvZ6h0K4HtS15UaVSBEaE+iln2LVpAuGc=
|
||||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||||
github.com/opencontainers/selinux v1.10.0 h1:rAiKF8hTcgLI3w0DHm6i0ylVVcOrlgR1kK99DRLDhyU=
|
|
||||||
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
|
||||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
|
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
|
||||||
@ -504,9 +496,8 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
|
|||||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||||
|
github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
|
||||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||||
github.com/prometheus/client_golang v1.11.1 h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s=
|
|
||||||
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
@ -539,7 +530,6 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
|
|||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
|
||||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
@ -608,7 +598,6 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
|
||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
||||||
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||||
@ -667,10 +656,8 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U
|
|||||||
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-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/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.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
|
||||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
|
||||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/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-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
@ -716,7 +703,6 @@ golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hM
|
|||||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -767,9 +753,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx
|
|||||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
|
||||||
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
|
||||||
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=
|
||||||
@ -797,7 +782,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@ -873,21 +857,25 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/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-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.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
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-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/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.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
|
||||||
golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||||
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
@ -896,6 +884,7 @@ golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2M
|
|||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@ -954,7 +943,6 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
|||||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff/go.mod h1:YD9qOF0M9xpSpdWTBbzEl5e/RnCefISl8E5Noe10jFM=
|
golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff/go.mod h1:YD9qOF0M9xpSpdWTBbzEl5e/RnCefISl8E5Noe10jFM=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|||||||
26
vendor/github.com/bits-and-blooms/bitset/.gitignore
generated
vendored
Normal file
26
vendor/github.com/bits-and-blooms/bitset/.gitignore
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Folders
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
*.test
|
||||||
|
*.prof
|
||||||
|
|
||||||
|
target
|
||||||
37
vendor/github.com/bits-and-blooms/bitset/.travis.yml
generated
vendored
Normal file
37
vendor/github.com/bits-and-blooms/bitset/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
language: go
|
||||||
|
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
branches:
|
||||||
|
except:
|
||||||
|
- release
|
||||||
|
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
- travis
|
||||||
|
|
||||||
|
go:
|
||||||
|
- "1.11.x"
|
||||||
|
- tip
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
allow_failures:
|
||||||
|
- go: tip
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- if [ -n "$GH_USER" ]; then git config --global github.user ${GH_USER}; fi;
|
||||||
|
- if [ -n "$GH_TOKEN" ]; then git config --global github.token ${GH_TOKEN}; fi;
|
||||||
|
- go get github.com/mattn/goveralls
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- make deps
|
||||||
|
|
||||||
|
script:
|
||||||
|
- make qa
|
||||||
|
|
||||||
|
after_failure:
|
||||||
|
- cat ./target/test/report.xml
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- if [ "$TRAVIS_GO_VERSION" = "1.11.1" ]; then $HOME/gopath/bin/goveralls -covermode=count -coverprofile=target/report/coverage.out -service=travis-ci; fi;
|
||||||
27
vendor/github.com/bits-and-blooms/bitset/LICENSE
generated
vendored
Normal file
27
vendor/github.com/bits-and-blooms/bitset/LICENSE
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Copyright (c) 2014 Will Fitzgerald. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
93
vendor/github.com/bits-and-blooms/bitset/README.md
generated
vendored
Normal file
93
vendor/github.com/bits-and-blooms/bitset/README.md
generated
vendored
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# bitset
|
||||||
|
|
||||||
|
*Go language library to map between non-negative integers and boolean values*
|
||||||
|
|
||||||
|
[](https://github.com/willf/bitset/actions?query=workflow%3ATest)
|
||||||
|
[](https://goreportcard.com/report/github.com/willf/bitset)
|
||||||
|
[](https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc)
|
||||||
|
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
Package bitset implements bitsets, a mapping between non-negative integers and boolean values.
|
||||||
|
It should be more efficient than map[uint] bool.
|
||||||
|
|
||||||
|
It provides methods for setting, clearing, flipping, and testing individual integers.
|
||||||
|
|
||||||
|
But it also provides set intersection, union, difference, complement, and symmetric operations, as well as tests to check whether any, all, or no bits are set, and querying a bitset's current length and number of positive bits.
|
||||||
|
|
||||||
|
BitSets are expanded to the size of the largest set bit; the memory allocation is approximately Max bits, where Max is the largest set bit. BitSets are never shrunk. On creation, a hint can be given for the number of bits that will be used.
|
||||||
|
|
||||||
|
Many of the methods, including Set, Clear, and Flip, return a BitSet pointer, which allows for chaining.
|
||||||
|
|
||||||
|
### Example use:
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
|
"github.com/bits-and-blooms/bitset"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Printf("Hello from BitSet!\n")
|
||||||
|
var b bitset.BitSet
|
||||||
|
// play some Go Fish
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
card1 := uint(rand.Intn(52))
|
||||||
|
card2 := uint(rand.Intn(52))
|
||||||
|
b.Set(card1)
|
||||||
|
if b.Test(card2) {
|
||||||
|
fmt.Println("Go Fish!")
|
||||||
|
}
|
||||||
|
b.Clear(card1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chaining
|
||||||
|
b.Set(10).Set(11)
|
||||||
|
|
||||||
|
for i, e := b.NextSet(0); e; i, e = b.NextSet(i + 1) {
|
||||||
|
fmt.Println("The following bit is set:", i)
|
||||||
|
}
|
||||||
|
if b.Intersection(bitset.New(100).Set(10)).Count() == 1 {
|
||||||
|
fmt.Println("Intersection works.")
|
||||||
|
} else {
|
||||||
|
fmt.Println("Intersection doesn't work???")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
As an alternative to BitSets, one should check out the 'big' package, which provides a (less set-theoretical) view of bitsets.
|
||||||
|
|
||||||
|
Package documentation is at: https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc
|
||||||
|
|
||||||
|
## Memory Usage
|
||||||
|
|
||||||
|
The memory usage of a bitset using N bits is at least N/8 bytes. The number of bits in a bitset is at least as large as one plus the greatest bit index you have accessed. Thus it is possible to run out of memory while using a bitset. If you have lots of bits, you might prefer compressed bitsets, like the [Roaring bitmaps](http://roaringbitmap.org) and its [Go implementation](https://github.com/RoaringBitmap/roaring).
|
||||||
|
|
||||||
|
## Implementation Note
|
||||||
|
|
||||||
|
Go 1.9 introduced a native `math/bits` library. We provide backward compatibility to Go 1.7, which might be removed.
|
||||||
|
|
||||||
|
It is possible that a later version will match the `math/bits` return signature for counts (which is `int`, rather than our library's `unit64`). If so, the version will be bumped.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go get github.com/bits-and-blooms/bitset
|
||||||
|
```
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
If you wish to contribute to this project, please branch and issue a pull request against master ("[GitHub Flow](https://guides.github.com/introduction/flow/)")
|
||||||
|
|
||||||
|
## Running all tests
|
||||||
|
|
||||||
|
Before committing the code, please check if it passes tests, has adequate coverage, etc.
|
||||||
|
```bash
|
||||||
|
go test
|
||||||
|
go test -cover
|
||||||
|
```
|
||||||
39
vendor/github.com/bits-and-blooms/bitset/azure-pipelines.yml
generated
vendored
Normal file
39
vendor/github.com/bits-and-blooms/bitset/azure-pipelines.yml
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# Go
|
||||||
|
# Build your Go project.
|
||||||
|
# Add steps that test, save build artifacts, deploy, and more:
|
||||||
|
# https://docs.microsoft.com/azure/devops/pipelines/languages/go
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
- master
|
||||||
|
|
||||||
|
pool:
|
||||||
|
vmImage: 'Ubuntu-16.04'
|
||||||
|
|
||||||
|
variables:
|
||||||
|
GOBIN: '$(GOPATH)/bin' # Go binaries path
|
||||||
|
GOROOT: '/usr/local/go1.11' # Go installation path
|
||||||
|
GOPATH: '$(system.defaultWorkingDirectory)/gopath' # Go workspace path
|
||||||
|
modulePath: '$(GOPATH)/src/github.com/$(build.repository.name)' # Path to the module's code
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- script: |
|
||||||
|
mkdir -p '$(GOBIN)'
|
||||||
|
mkdir -p '$(GOPATH)/pkg'
|
||||||
|
mkdir -p '$(modulePath)'
|
||||||
|
shopt -s extglob
|
||||||
|
shopt -s dotglob
|
||||||
|
mv !(gopath) '$(modulePath)'
|
||||||
|
echo '##vso[task.prependpath]$(GOBIN)'
|
||||||
|
echo '##vso[task.prependpath]$(GOROOT)/bin'
|
||||||
|
displayName: 'Set up the Go workspace'
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
go version
|
||||||
|
go get -v -t -d ./...
|
||||||
|
if [ -f Gopkg.toml ]; then
|
||||||
|
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
|
||||||
|
dep ensure
|
||||||
|
fi
|
||||||
|
go build -v .
|
||||||
|
workingDirectory: '$(modulePath)'
|
||||||
|
displayName: 'Get dependencies, then build'
|
||||||
952
vendor/github.com/bits-and-blooms/bitset/bitset.go
generated
vendored
Normal file
952
vendor/github.com/bits-and-blooms/bitset/bitset.go
generated
vendored
Normal file
@ -0,0 +1,952 @@
|
|||||||
|
/*
|
||||||
|
Package bitset implements bitsets, a mapping
|
||||||
|
between non-negative integers and boolean values. It should be more
|
||||||
|
efficient than map[uint] bool.
|
||||||
|
|
||||||
|
It provides methods for setting, clearing, flipping, and testing
|
||||||
|
individual integers.
|
||||||
|
|
||||||
|
But it also provides set intersection, union, difference,
|
||||||
|
complement, and symmetric operations, as well as tests to
|
||||||
|
check whether any, all, or no bits are set, and querying a
|
||||||
|
bitset's current length and number of positive bits.
|
||||||
|
|
||||||
|
BitSets are expanded to the size of the largest set bit; the
|
||||||
|
memory allocation is approximately Max bits, where Max is
|
||||||
|
the largest set bit. BitSets are never shrunk. On creation,
|
||||||
|
a hint can be given for the number of bits that will be used.
|
||||||
|
|
||||||
|
Many of the methods, including Set,Clear, and Flip, return
|
||||||
|
a BitSet pointer, which allows for chaining.
|
||||||
|
|
||||||
|
Example use:
|
||||||
|
|
||||||
|
import "bitset"
|
||||||
|
var b BitSet
|
||||||
|
b.Set(10).Set(11)
|
||||||
|
if b.Test(1000) {
|
||||||
|
b.Clear(1000)
|
||||||
|
}
|
||||||
|
if B.Intersection(bitset.New(100).Set(10)).Count() > 1 {
|
||||||
|
fmt.Println("Intersection works.")
|
||||||
|
}
|
||||||
|
|
||||||
|
As an alternative to BitSets, one should check out the 'big' package,
|
||||||
|
which provides a (less set-theoretical) view of bitsets.
|
||||||
|
|
||||||
|
*/
|
||||||
|
package bitset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// the wordSize of a bit set
|
||||||
|
const wordSize = uint(64)
|
||||||
|
|
||||||
|
// log2WordSize is lg(wordSize)
|
||||||
|
const log2WordSize = uint(6)
|
||||||
|
|
||||||
|
// allBits has every bit set
|
||||||
|
const allBits uint64 = 0xffffffffffffffff
|
||||||
|
|
||||||
|
// default binary BigEndian
|
||||||
|
var binaryOrder binary.ByteOrder = binary.BigEndian
|
||||||
|
|
||||||
|
// default json encoding base64.URLEncoding
|
||||||
|
var base64Encoding = base64.URLEncoding
|
||||||
|
|
||||||
|
// Base64StdEncoding Marshal/Unmarshal BitSet with base64.StdEncoding(Default: base64.URLEncoding)
|
||||||
|
func Base64StdEncoding() { base64Encoding = base64.StdEncoding }
|
||||||
|
|
||||||
|
// LittleEndian Marshal/Unmarshal Binary as Little Endian(Default: binary.BigEndian)
|
||||||
|
func LittleEndian() { binaryOrder = binary.LittleEndian }
|
||||||
|
|
||||||
|
// A BitSet is a set of bits. The zero value of a BitSet is an empty set of length 0.
|
||||||
|
type BitSet struct {
|
||||||
|
length uint
|
||||||
|
set []uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error is used to distinguish errors (panics) generated in this package.
|
||||||
|
type Error string
|
||||||
|
|
||||||
|
// safeSet will fixup b.set to be non-nil and return the field value
|
||||||
|
func (b *BitSet) safeSet() []uint64 {
|
||||||
|
if b.set == nil {
|
||||||
|
b.set = make([]uint64, wordsNeeded(0))
|
||||||
|
}
|
||||||
|
return b.set
|
||||||
|
}
|
||||||
|
|
||||||
|
// From is a constructor used to create a BitSet from an array of integers
|
||||||
|
func From(buf []uint64) *BitSet {
|
||||||
|
return &BitSet{uint(len(buf)) * 64, buf}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes returns the bitset as array of integers
|
||||||
|
func (b *BitSet) Bytes() []uint64 {
|
||||||
|
return b.set
|
||||||
|
}
|
||||||
|
|
||||||
|
// wordsNeeded calculates the number of words needed for i bits
|
||||||
|
func wordsNeeded(i uint) int {
|
||||||
|
if i > (Cap() - wordSize + 1) {
|
||||||
|
return int(Cap() >> log2WordSize)
|
||||||
|
}
|
||||||
|
return int((i + (wordSize - 1)) >> log2WordSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new BitSet with a hint that length bits will be required
|
||||||
|
func New(length uint) (bset *BitSet) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
bset = &BitSet{
|
||||||
|
0,
|
||||||
|
make([]uint64, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
bset = &BitSet{
|
||||||
|
length,
|
||||||
|
make([]uint64, wordsNeeded(length)),
|
||||||
|
}
|
||||||
|
|
||||||
|
return bset
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cap returns the total possible capacity, or number of bits
|
||||||
|
func Cap() uint {
|
||||||
|
return ^uint(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the number of bits in the BitSet.
|
||||||
|
// Note the difference to method Count, see example.
|
||||||
|
func (b *BitSet) Len() uint {
|
||||||
|
return b.length
|
||||||
|
}
|
||||||
|
|
||||||
|
// extendSetMaybe adds additional words to incorporate new bits if needed
|
||||||
|
func (b *BitSet) extendSetMaybe(i uint) {
|
||||||
|
if i >= b.length { // if we need more bits, make 'em
|
||||||
|
if i >= Cap() {
|
||||||
|
panic("You are exceeding the capacity")
|
||||||
|
}
|
||||||
|
nsize := wordsNeeded(i + 1)
|
||||||
|
if b.set == nil {
|
||||||
|
b.set = make([]uint64, nsize)
|
||||||
|
} else if cap(b.set) >= nsize {
|
||||||
|
b.set = b.set[:nsize] // fast resize
|
||||||
|
} else if len(b.set) < nsize {
|
||||||
|
newset := make([]uint64, nsize, 2*nsize) // increase capacity 2x
|
||||||
|
copy(newset, b.set)
|
||||||
|
b.set = newset
|
||||||
|
}
|
||||||
|
b.length = i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test whether bit i is set.
|
||||||
|
func (b *BitSet) Test(i uint) bool {
|
||||||
|
if i >= b.length {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return b.set[i>>log2WordSize]&(1<<(i&(wordSize-1))) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set bit i to 1, the capacity of the bitset is automatically
|
||||||
|
// increased accordingly.
|
||||||
|
// If i>= Cap(), this function will panic.
|
||||||
|
// Warning: using a very large value for 'i'
|
||||||
|
// may lead to a memory shortage and a panic: the caller is responsible
|
||||||
|
// for providing sensible parameters in line with their memory capacity.
|
||||||
|
func (b *BitSet) Set(i uint) *BitSet {
|
||||||
|
b.extendSetMaybe(i)
|
||||||
|
b.set[i>>log2WordSize] |= 1 << (i & (wordSize - 1))
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear bit i to 0
|
||||||
|
func (b *BitSet) Clear(i uint) *BitSet {
|
||||||
|
if i >= b.length {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
b.set[i>>log2WordSize] &^= 1 << (i & (wordSize - 1))
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo sets bit i to value.
|
||||||
|
// If i>= Cap(), this function will panic.
|
||||||
|
// Warning: using a very large value for 'i'
|
||||||
|
// may lead to a memory shortage and a panic: the caller is responsible
|
||||||
|
// for providing sensible parameters in line with their memory capacity.
|
||||||
|
func (b *BitSet) SetTo(i uint, value bool) *BitSet {
|
||||||
|
if value {
|
||||||
|
return b.Set(i)
|
||||||
|
}
|
||||||
|
return b.Clear(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flip bit at i.
|
||||||
|
// If i>= Cap(), this function will panic.
|
||||||
|
// Warning: using a very large value for 'i'
|
||||||
|
// may lead to a memory shortage and a panic: the caller is responsible
|
||||||
|
// for providing sensible parameters in line with their memory capacity.
|
||||||
|
func (b *BitSet) Flip(i uint) *BitSet {
|
||||||
|
if i >= b.length {
|
||||||
|
return b.Set(i)
|
||||||
|
}
|
||||||
|
b.set[i>>log2WordSize] ^= 1 << (i & (wordSize - 1))
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlipRange bit in [start, end).
|
||||||
|
// If end>= Cap(), this function will panic.
|
||||||
|
// Warning: using a very large value for 'end'
|
||||||
|
// may lead to a memory shortage and a panic: the caller is responsible
|
||||||
|
// for providing sensible parameters in line with their memory capacity.
|
||||||
|
func (b *BitSet) FlipRange(start, end uint) *BitSet {
|
||||||
|
if start >= end {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
b.extendSetMaybe(end - 1)
|
||||||
|
var startWord uint = start >> log2WordSize
|
||||||
|
var endWord uint = end >> log2WordSize
|
||||||
|
b.set[startWord] ^= ^(^uint64(0) << (start & (wordSize - 1)))
|
||||||
|
for i := startWord; i < endWord; i++ {
|
||||||
|
b.set[i] = ^b.set[i]
|
||||||
|
}
|
||||||
|
b.set[endWord] ^= ^uint64(0) >> (-end & (wordSize - 1))
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shrink shrinks BitSet so that the provided value is the last possible
|
||||||
|
// set value. It clears all bits > the provided index and reduces the size
|
||||||
|
// and length of the set.
|
||||||
|
//
|
||||||
|
// Note that the parameter value is not the new length in bits: it is the
|
||||||
|
// maximal value that can be stored in the bitset after the function call.
|
||||||
|
// The new length in bits is the parameter value + 1. Thus it is not possible
|
||||||
|
// to use this function to set the length to 0, the minimal value of the length
|
||||||
|
// after this function call is 1.
|
||||||
|
//
|
||||||
|
// A new slice is allocated to store the new bits, so you may see an increase in
|
||||||
|
// memory usage until the GC runs. Normally this should not be a problem, but if you
|
||||||
|
// have an extremely large BitSet its important to understand that the old BitSet will
|
||||||
|
// remain in memory until the GC frees it.
|
||||||
|
func (b *BitSet) Shrink(lastbitindex uint) *BitSet {
|
||||||
|
length := lastbitindex + 1
|
||||||
|
idx := wordsNeeded(length)
|
||||||
|
if idx > len(b.set) {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
shrunk := make([]uint64, idx)
|
||||||
|
copy(shrunk, b.set[:idx])
|
||||||
|
b.set = shrunk
|
||||||
|
b.length = length
|
||||||
|
b.set[idx-1] &= (allBits >> (uint64(64) - uint64(length&(wordSize-1))))
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compact shrinks BitSet to so that we preserve all set bits, while minimizing
|
||||||
|
// memory usage. Compact calls Shrink.
|
||||||
|
func (b *BitSet) Compact() *BitSet {
|
||||||
|
idx := len(b.set) - 1
|
||||||
|
for ; idx >= 0 && b.set[idx] == 0; idx-- {
|
||||||
|
}
|
||||||
|
newlength := uint((idx + 1) << log2WordSize)
|
||||||
|
if newlength >= b.length {
|
||||||
|
return b // nothing to do
|
||||||
|
}
|
||||||
|
if newlength > 0 {
|
||||||
|
return b.Shrink(newlength - 1)
|
||||||
|
}
|
||||||
|
// We preserve one word
|
||||||
|
return b.Shrink(63)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InsertAt takes an index which indicates where a bit should be
|
||||||
|
// inserted. Then it shifts all the bits in the set to the left by 1, starting
|
||||||
|
// from the given index position, and sets the index position to 0.
|
||||||
|
//
|
||||||
|
// Depending on the size of your BitSet, and where you are inserting the new entry,
|
||||||
|
// this method could be extremely slow and in some cases might cause the entire BitSet
|
||||||
|
// to be recopied.
|
||||||
|
func (b *BitSet) InsertAt(idx uint) *BitSet {
|
||||||
|
insertAtElement := (idx >> log2WordSize)
|
||||||
|
|
||||||
|
// if length of set is a multiple of wordSize we need to allocate more space first
|
||||||
|
if b.isLenExactMultiple() {
|
||||||
|
b.set = append(b.set, uint64(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
var i uint
|
||||||
|
for i = uint(len(b.set) - 1); i > insertAtElement; i-- {
|
||||||
|
// all elements above the position where we want to insert can simply by shifted
|
||||||
|
b.set[i] <<= 1
|
||||||
|
|
||||||
|
// we take the most significant bit of the previous element and set it as
|
||||||
|
// the least significant bit of the current element
|
||||||
|
b.set[i] |= (b.set[i-1] & 0x8000000000000000) >> 63
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate a mask to extract the data that we need to shift left
|
||||||
|
// within the element where we insert a bit
|
||||||
|
dataMask := ^(uint64(1)<<uint64(idx&(wordSize-1)) - 1)
|
||||||
|
|
||||||
|
// extract that data that we'll shift
|
||||||
|
data := b.set[i] & dataMask
|
||||||
|
|
||||||
|
// set the positions of the data mask to 0 in the element where we insert
|
||||||
|
b.set[i] &= ^dataMask
|
||||||
|
|
||||||
|
// shift data mask to the left and insert its data to the slice element
|
||||||
|
b.set[i] |= data << 1
|
||||||
|
|
||||||
|
// add 1 to length of BitSet
|
||||||
|
b.length++
|
||||||
|
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// String creates a string representation of the Bitmap
|
||||||
|
func (b *BitSet) String() string {
|
||||||
|
// follows code from https://github.com/RoaringBitmap/roaring
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
start := []byte("{")
|
||||||
|
buffer.Write(start)
|
||||||
|
counter := 0
|
||||||
|
i, e := b.NextSet(0)
|
||||||
|
for e {
|
||||||
|
counter = counter + 1
|
||||||
|
// to avoid exhausting the memory
|
||||||
|
if counter > 0x40000 {
|
||||||
|
buffer.WriteString("...")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
buffer.WriteString(strconv.FormatInt(int64(i), 10))
|
||||||
|
i, e = b.NextSet(i + 1)
|
||||||
|
if e {
|
||||||
|
buffer.WriteString(",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer.WriteString("}")
|
||||||
|
return buffer.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteAt deletes the bit at the given index position from
|
||||||
|
// within the bitset
|
||||||
|
// All the bits residing on the left of the deleted bit get
|
||||||
|
// shifted right by 1
|
||||||
|
// The running time of this operation may potentially be
|
||||||
|
// relatively slow, O(length)
|
||||||
|
func (b *BitSet) DeleteAt(i uint) *BitSet {
|
||||||
|
// the index of the slice element where we'll delete a bit
|
||||||
|
deleteAtElement := i >> log2WordSize
|
||||||
|
|
||||||
|
// generate a mask for the data that needs to be shifted right
|
||||||
|
// within that slice element that gets modified
|
||||||
|
dataMask := ^((uint64(1) << (i & (wordSize - 1))) - 1)
|
||||||
|
|
||||||
|
// extract the data that we'll shift right from the slice element
|
||||||
|
data := b.set[deleteAtElement] & dataMask
|
||||||
|
|
||||||
|
// set the masked area to 0 while leaving the rest as it is
|
||||||
|
b.set[deleteAtElement] &= ^dataMask
|
||||||
|
|
||||||
|
// shift the previously extracted data to the right and then
|
||||||
|
// set it in the previously masked area
|
||||||
|
b.set[deleteAtElement] |= (data >> 1) & dataMask
|
||||||
|
|
||||||
|
// loop over all the consecutive slice elements to copy each
|
||||||
|
// lowest bit into the highest position of the previous element,
|
||||||
|
// then shift the entire content to the right by 1
|
||||||
|
for i := int(deleteAtElement) + 1; i < len(b.set); i++ {
|
||||||
|
b.set[i-1] |= (b.set[i] & 1) << 63
|
||||||
|
b.set[i] >>= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
b.length = b.length - 1
|
||||||
|
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextSet returns the next bit set from the specified index,
|
||||||
|
// including possibly the current index
|
||||||
|
// along with an error code (true = valid, false = no set bit found)
|
||||||
|
// for i,e := v.NextSet(0); e; i,e = v.NextSet(i + 1) {...}
|
||||||
|
//
|
||||||
|
// Users concerned with performance may want to use NextSetMany to
|
||||||
|
// retrieve several values at once.
|
||||||
|
func (b *BitSet) NextSet(i uint) (uint, bool) {
|
||||||
|
x := int(i >> log2WordSize)
|
||||||
|
if x >= len(b.set) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
w := b.set[x]
|
||||||
|
w = w >> (i & (wordSize - 1))
|
||||||
|
if w != 0 {
|
||||||
|
return i + trailingZeroes64(w), true
|
||||||
|
}
|
||||||
|
x = x + 1
|
||||||
|
for x < len(b.set) {
|
||||||
|
if b.set[x] != 0 {
|
||||||
|
return uint(x)*wordSize + trailingZeroes64(b.set[x]), true
|
||||||
|
}
|
||||||
|
x = x + 1
|
||||||
|
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextSetMany returns many next bit sets from the specified index,
|
||||||
|
// including possibly the current index and up to cap(buffer).
|
||||||
|
// If the returned slice has len zero, then no more set bits were found
|
||||||
|
//
|
||||||
|
// buffer := make([]uint, 256) // this should be reused
|
||||||
|
// j := uint(0)
|
||||||
|
// j, buffer = bitmap.NextSetMany(j, buffer)
|
||||||
|
// for ; len(buffer) > 0; j, buffer = bitmap.NextSetMany(j,buffer) {
|
||||||
|
// for k := range buffer {
|
||||||
|
// do something with buffer[k]
|
||||||
|
// }
|
||||||
|
// j += 1
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// It is possible to retrieve all set bits as follow:
|
||||||
|
//
|
||||||
|
// indices := make([]uint, bitmap.Count())
|
||||||
|
// bitmap.NextSetMany(0, indices)
|
||||||
|
//
|
||||||
|
// However if bitmap.Count() is large, it might be preferable to
|
||||||
|
// use several calls to NextSetMany, for performance reasons.
|
||||||
|
func (b *BitSet) NextSetMany(i uint, buffer []uint) (uint, []uint) {
|
||||||
|
myanswer := buffer
|
||||||
|
capacity := cap(buffer)
|
||||||
|
x := int(i >> log2WordSize)
|
||||||
|
if x >= len(b.set) || capacity == 0 {
|
||||||
|
return 0, myanswer[:0]
|
||||||
|
}
|
||||||
|
skip := i & (wordSize - 1)
|
||||||
|
word := b.set[x] >> skip
|
||||||
|
myanswer = myanswer[:capacity]
|
||||||
|
size := int(0)
|
||||||
|
for word != 0 {
|
||||||
|
r := trailingZeroes64(word)
|
||||||
|
t := word & ((^word) + 1)
|
||||||
|
myanswer[size] = r + i
|
||||||
|
size++
|
||||||
|
if size == capacity {
|
||||||
|
goto End
|
||||||
|
}
|
||||||
|
word = word ^ t
|
||||||
|
}
|
||||||
|
x++
|
||||||
|
for idx, word := range b.set[x:] {
|
||||||
|
for word != 0 {
|
||||||
|
r := trailingZeroes64(word)
|
||||||
|
t := word & ((^word) + 1)
|
||||||
|
myanswer[size] = r + (uint(x+idx) << 6)
|
||||||
|
size++
|
||||||
|
if size == capacity {
|
||||||
|
goto End
|
||||||
|
}
|
||||||
|
word = word ^ t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
End:
|
||||||
|
if size > 0 {
|
||||||
|
return myanswer[size-1], myanswer[:size]
|
||||||
|
}
|
||||||
|
return 0, myanswer[:0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextClear returns the next clear bit from the specified index,
|
||||||
|
// including possibly the current index
|
||||||
|
// along with an error code (true = valid, false = no bit found i.e. all bits are set)
|
||||||
|
func (b *BitSet) NextClear(i uint) (uint, bool) {
|
||||||
|
x := int(i >> log2WordSize)
|
||||||
|
if x >= len(b.set) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
w := b.set[x]
|
||||||
|
w = w >> (i & (wordSize - 1))
|
||||||
|
wA := allBits >> (i & (wordSize - 1))
|
||||||
|
index := i + trailingZeroes64(^w)
|
||||||
|
if w != wA && index < b.length {
|
||||||
|
return index, true
|
||||||
|
}
|
||||||
|
x++
|
||||||
|
for x < len(b.set) {
|
||||||
|
index = uint(x)*wordSize + trailingZeroes64(^b.set[x])
|
||||||
|
if b.set[x] != allBits && index < b.length {
|
||||||
|
return index, true
|
||||||
|
}
|
||||||
|
x++
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearAll clears the entire BitSet
|
||||||
|
func (b *BitSet) ClearAll() *BitSet {
|
||||||
|
if b != nil && b.set != nil {
|
||||||
|
for i := range b.set {
|
||||||
|
b.set[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// wordCount returns the number of words used in a bit set
|
||||||
|
func (b *BitSet) wordCount() int {
|
||||||
|
return len(b.set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone this BitSet
|
||||||
|
func (b *BitSet) Clone() *BitSet {
|
||||||
|
c := New(b.length)
|
||||||
|
if b.set != nil { // Clone should not modify current object
|
||||||
|
copy(c.set, b.set)
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy into a destination BitSet
|
||||||
|
// Returning the size of the destination BitSet
|
||||||
|
// like array copy
|
||||||
|
func (b *BitSet) Copy(c *BitSet) (count uint) {
|
||||||
|
if c == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if b.set != nil { // Copy should not modify current object
|
||||||
|
copy(c.set, b.set)
|
||||||
|
}
|
||||||
|
count = c.length
|
||||||
|
if b.length < c.length {
|
||||||
|
count = b.length
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count (number of set bits).
|
||||||
|
// Also known as "popcount" or "population count".
|
||||||
|
func (b *BitSet) Count() uint {
|
||||||
|
if b != nil && b.set != nil {
|
||||||
|
return uint(popcntSlice(b.set))
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal tests the equivalence of two BitSets.
|
||||||
|
// False if they are of different sizes, otherwise true
|
||||||
|
// only if all the same bits are set
|
||||||
|
func (b *BitSet) Equal(c *BitSet) bool {
|
||||||
|
if c == nil || b == nil {
|
||||||
|
return c == b
|
||||||
|
}
|
||||||
|
if b.length != c.length {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if b.length == 0 { // if they have both length == 0, then could have nil set
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// testing for equality shoud not transform the bitset (no call to safeSet)
|
||||||
|
|
||||||
|
for p, v := range b.set {
|
||||||
|
if c.set[p] != v {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func panicIfNull(b *BitSet) {
|
||||||
|
if b == nil {
|
||||||
|
panic(Error("BitSet must not be null"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Difference of base set and other set
|
||||||
|
// This is the BitSet equivalent of &^ (and not)
|
||||||
|
func (b *BitSet) Difference(compare *BitSet) (result *BitSet) {
|
||||||
|
panicIfNull(b)
|
||||||
|
panicIfNull(compare)
|
||||||
|
result = b.Clone() // clone b (in case b is bigger than compare)
|
||||||
|
l := int(compare.wordCount())
|
||||||
|
if l > int(b.wordCount()) {
|
||||||
|
l = int(b.wordCount())
|
||||||
|
}
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
result.set[i] = b.set[i] &^ compare.set[i]
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DifferenceCardinality computes the cardinality of the differnce
|
||||||
|
func (b *BitSet) DifferenceCardinality(compare *BitSet) uint {
|
||||||
|
panicIfNull(b)
|
||||||
|
panicIfNull(compare)
|
||||||
|
l := int(compare.wordCount())
|
||||||
|
if l > int(b.wordCount()) {
|
||||||
|
l = int(b.wordCount())
|
||||||
|
}
|
||||||
|
cnt := uint64(0)
|
||||||
|
cnt += popcntMaskSlice(b.set[:l], compare.set[:l])
|
||||||
|
cnt += popcntSlice(b.set[l:])
|
||||||
|
return uint(cnt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InPlaceDifference computes the difference of base set and other set
|
||||||
|
// This is the BitSet equivalent of &^ (and not)
|
||||||
|
func (b *BitSet) InPlaceDifference(compare *BitSet) {
|
||||||
|
panicIfNull(b)
|
||||||
|
panicIfNull(compare)
|
||||||
|
l := int(compare.wordCount())
|
||||||
|
if l > int(b.wordCount()) {
|
||||||
|
l = int(b.wordCount())
|
||||||
|
}
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
b.set[i] &^= compare.set[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience function: return two bitsets ordered by
|
||||||
|
// increasing length. Note: neither can be nil
|
||||||
|
func sortByLength(a *BitSet, b *BitSet) (ap *BitSet, bp *BitSet) {
|
||||||
|
if a.length <= b.length {
|
||||||
|
ap, bp = a, b
|
||||||
|
} else {
|
||||||
|
ap, bp = b, a
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intersection of base set and other set
|
||||||
|
// This is the BitSet equivalent of & (and)
|
||||||
|
func (b *BitSet) Intersection(compare *BitSet) (result *BitSet) {
|
||||||
|
panicIfNull(b)
|
||||||
|
panicIfNull(compare)
|
||||||
|
b, compare = sortByLength(b, compare)
|
||||||
|
result = New(b.length)
|
||||||
|
for i, word := range b.set {
|
||||||
|
result.set[i] = word & compare.set[i]
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntersectionCardinality computes the cardinality of the union
|
||||||
|
func (b *BitSet) IntersectionCardinality(compare *BitSet) uint {
|
||||||
|
panicIfNull(b)
|
||||||
|
panicIfNull(compare)
|
||||||
|
b, compare = sortByLength(b, compare)
|
||||||
|
cnt := popcntAndSlice(b.set, compare.set)
|
||||||
|
return uint(cnt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InPlaceIntersection destructively computes the intersection of
|
||||||
|
// base set and the compare set.
|
||||||
|
// This is the BitSet equivalent of & (and)
|
||||||
|
func (b *BitSet) InPlaceIntersection(compare *BitSet) {
|
||||||
|
panicIfNull(b)
|
||||||
|
panicIfNull(compare)
|
||||||
|
l := int(compare.wordCount())
|
||||||
|
if l > int(b.wordCount()) {
|
||||||
|
l = int(b.wordCount())
|
||||||
|
}
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
b.set[i] &= compare.set[i]
|
||||||
|
}
|
||||||
|
for i := l; i < len(b.set); i++ {
|
||||||
|
b.set[i] = 0
|
||||||
|
}
|
||||||
|
if compare.length > 0 {
|
||||||
|
b.extendSetMaybe(compare.length - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union of base set and other set
|
||||||
|
// This is the BitSet equivalent of | (or)
|
||||||
|
func (b *BitSet) Union(compare *BitSet) (result *BitSet) {
|
||||||
|
panicIfNull(b)
|
||||||
|
panicIfNull(compare)
|
||||||
|
b, compare = sortByLength(b, compare)
|
||||||
|
result = compare.Clone()
|
||||||
|
for i, word := range b.set {
|
||||||
|
result.set[i] = word | compare.set[i]
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnionCardinality computes the cardinality of the uniton of the base set
|
||||||
|
// and the compare set.
|
||||||
|
func (b *BitSet) UnionCardinality(compare *BitSet) uint {
|
||||||
|
panicIfNull(b)
|
||||||
|
panicIfNull(compare)
|
||||||
|
b, compare = sortByLength(b, compare)
|
||||||
|
cnt := popcntOrSlice(b.set, compare.set)
|
||||||
|
if len(compare.set) > len(b.set) {
|
||||||
|
cnt += popcntSlice(compare.set[len(b.set):])
|
||||||
|
}
|
||||||
|
return uint(cnt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InPlaceUnion creates the destructive union of base set and compare set.
|
||||||
|
// This is the BitSet equivalent of | (or).
|
||||||
|
func (b *BitSet) InPlaceUnion(compare *BitSet) {
|
||||||
|
panicIfNull(b)
|
||||||
|
panicIfNull(compare)
|
||||||
|
l := int(compare.wordCount())
|
||||||
|
if l > int(b.wordCount()) {
|
||||||
|
l = int(b.wordCount())
|
||||||
|
}
|
||||||
|
if compare.length > 0 {
|
||||||
|
b.extendSetMaybe(compare.length - 1)
|
||||||
|
}
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
b.set[i] |= compare.set[i]
|
||||||
|
}
|
||||||
|
if len(compare.set) > l {
|
||||||
|
for i := l; i < len(compare.set); i++ {
|
||||||
|
b.set[i] = compare.set[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SymmetricDifference of base set and other set
|
||||||
|
// This is the BitSet equivalent of ^ (xor)
|
||||||
|
func (b *BitSet) SymmetricDifference(compare *BitSet) (result *BitSet) {
|
||||||
|
panicIfNull(b)
|
||||||
|
panicIfNull(compare)
|
||||||
|
b, compare = sortByLength(b, compare)
|
||||||
|
// compare is bigger, so clone it
|
||||||
|
result = compare.Clone()
|
||||||
|
for i, word := range b.set {
|
||||||
|
result.set[i] = word ^ compare.set[i]
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// SymmetricDifferenceCardinality computes the cardinality of the symmetric difference
|
||||||
|
func (b *BitSet) SymmetricDifferenceCardinality(compare *BitSet) uint {
|
||||||
|
panicIfNull(b)
|
||||||
|
panicIfNull(compare)
|
||||||
|
b, compare = sortByLength(b, compare)
|
||||||
|
cnt := popcntXorSlice(b.set, compare.set)
|
||||||
|
if len(compare.set) > len(b.set) {
|
||||||
|
cnt += popcntSlice(compare.set[len(b.set):])
|
||||||
|
}
|
||||||
|
return uint(cnt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InPlaceSymmetricDifference creates the destructive SymmetricDifference of base set and other set
|
||||||
|
// This is the BitSet equivalent of ^ (xor)
|
||||||
|
func (b *BitSet) InPlaceSymmetricDifference(compare *BitSet) {
|
||||||
|
panicIfNull(b)
|
||||||
|
panicIfNull(compare)
|
||||||
|
l := int(compare.wordCount())
|
||||||
|
if l > int(b.wordCount()) {
|
||||||
|
l = int(b.wordCount())
|
||||||
|
}
|
||||||
|
if compare.length > 0 {
|
||||||
|
b.extendSetMaybe(compare.length - 1)
|
||||||
|
}
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
b.set[i] ^= compare.set[i]
|
||||||
|
}
|
||||||
|
if len(compare.set) > l {
|
||||||
|
for i := l; i < len(compare.set); i++ {
|
||||||
|
b.set[i] = compare.set[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the length an exact multiple of word sizes?
|
||||||
|
func (b *BitSet) isLenExactMultiple() bool {
|
||||||
|
return b.length%wordSize == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean last word by setting unused bits to 0
|
||||||
|
func (b *BitSet) cleanLastWord() {
|
||||||
|
if !b.isLenExactMultiple() {
|
||||||
|
b.set[len(b.set)-1] &= allBits >> (wordSize - b.length%wordSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Complement computes the (local) complement of a biset (up to length bits)
|
||||||
|
func (b *BitSet) Complement() (result *BitSet) {
|
||||||
|
panicIfNull(b)
|
||||||
|
result = New(b.length)
|
||||||
|
for i, word := range b.set {
|
||||||
|
result.set[i] = ^word
|
||||||
|
}
|
||||||
|
result.cleanLastWord()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// All returns true if all bits are set, false otherwise. Returns true for
|
||||||
|
// empty sets.
|
||||||
|
func (b *BitSet) All() bool {
|
||||||
|
panicIfNull(b)
|
||||||
|
return b.Count() == b.length
|
||||||
|
}
|
||||||
|
|
||||||
|
// None returns true if no bit is set, false otherwise. Returns true for
|
||||||
|
// empty sets.
|
||||||
|
func (b *BitSet) None() bool {
|
||||||
|
panicIfNull(b)
|
||||||
|
if b != nil && b.set != nil {
|
||||||
|
for _, word := range b.set {
|
||||||
|
if word > 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any returns true if any bit is set, false otherwise
|
||||||
|
func (b *BitSet) Any() bool {
|
||||||
|
panicIfNull(b)
|
||||||
|
return !b.None()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSuperSet returns true if this is a superset of the other set
|
||||||
|
func (b *BitSet) IsSuperSet(other *BitSet) bool {
|
||||||
|
for i, e := other.NextSet(0); e; i, e = other.NextSet(i + 1) {
|
||||||
|
if !b.Test(i) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsStrictSuperSet returns true if this is a strict superset of the other set
|
||||||
|
func (b *BitSet) IsStrictSuperSet(other *BitSet) bool {
|
||||||
|
return b.Count() > other.Count() && b.IsSuperSet(other)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DumpAsBits dumps a bit set as a string of bits
|
||||||
|
func (b *BitSet) DumpAsBits() string {
|
||||||
|
if b.set == nil {
|
||||||
|
return "."
|
||||||
|
}
|
||||||
|
buffer := bytes.NewBufferString("")
|
||||||
|
i := len(b.set) - 1
|
||||||
|
for ; i >= 0; i-- {
|
||||||
|
fmt.Fprintf(buffer, "%064b.", b.set[i])
|
||||||
|
}
|
||||||
|
return buffer.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// BinaryStorageSize returns the binary storage requirements
|
||||||
|
func (b *BitSet) BinaryStorageSize() int {
|
||||||
|
return binary.Size(uint64(0)) + binary.Size(b.set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteTo writes a BitSet to a stream
|
||||||
|
func (b *BitSet) WriteTo(stream io.Writer) (int64, error) {
|
||||||
|
length := uint64(b.length)
|
||||||
|
|
||||||
|
// Write length
|
||||||
|
err := binary.Write(stream, binaryOrder, length)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write set
|
||||||
|
err = binary.Write(stream, binaryOrder, b.set)
|
||||||
|
return int64(b.BinaryStorageSize()), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadFrom reads a BitSet from a stream written using WriteTo
|
||||||
|
func (b *BitSet) ReadFrom(stream io.Reader) (int64, error) {
|
||||||
|
var length uint64
|
||||||
|
|
||||||
|
// Read length first
|
||||||
|
err := binary.Read(stream, binaryOrder, &length)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
newset := New(uint(length))
|
||||||
|
|
||||||
|
if uint64(newset.length) != length {
|
||||||
|
return 0, errors.New("unmarshalling error: type mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read remaining bytes as set
|
||||||
|
err = binary.Read(stream, binaryOrder, newset.set)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
*b = *newset
|
||||||
|
return int64(b.BinaryStorageSize()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalBinary encodes a BitSet into a binary form and returns the result.
|
||||||
|
func (b *BitSet) MarshalBinary() ([]byte, error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
writer := bufio.NewWriter(&buf)
|
||||||
|
|
||||||
|
_, err := b.WriteTo(writer)
|
||||||
|
if err != nil {
|
||||||
|
return []byte{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = writer.Flush()
|
||||||
|
|
||||||
|
return buf.Bytes(), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBinary decodes the binary form generated by MarshalBinary.
|
||||||
|
func (b *BitSet) UnmarshalBinary(data []byte) error {
|
||||||
|
buf := bytes.NewReader(data)
|
||||||
|
reader := bufio.NewReader(buf)
|
||||||
|
|
||||||
|
_, err := b.ReadFrom(reader)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON marshals a BitSet as a JSON structure
|
||||||
|
func (b *BitSet) MarshalJSON() ([]byte, error) {
|
||||||
|
buffer := bytes.NewBuffer(make([]byte, 0, b.BinaryStorageSize()))
|
||||||
|
_, err := b.WriteTo(buffer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// URLEncode all bytes
|
||||||
|
return json.Marshal(base64Encoding.EncodeToString(buffer.Bytes()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals a BitSet from JSON created using MarshalJSON
|
||||||
|
func (b *BitSet) UnmarshalJSON(data []byte) error {
|
||||||
|
// Unmarshal as string
|
||||||
|
var s string
|
||||||
|
err := json.Unmarshal(data, &s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// URLDecode string
|
||||||
|
buf, err := base64Encoding.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = b.ReadFrom(bytes.NewReader(buf))
|
||||||
|
return err
|
||||||
|
}
|
||||||
53
vendor/github.com/bits-and-blooms/bitset/popcnt.go
generated
vendored
Normal file
53
vendor/github.com/bits-and-blooms/bitset/popcnt.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package bitset
|
||||||
|
|
||||||
|
// bit population count, take from
|
||||||
|
// https://code.google.com/p/go/issues/detail?id=4988#c11
|
||||||
|
// credit: https://code.google.com/u/arnehormann/
|
||||||
|
func popcount(x uint64) (n uint64) {
|
||||||
|
x -= (x >> 1) & 0x5555555555555555
|
||||||
|
x = (x>>2)&0x3333333333333333 + x&0x3333333333333333
|
||||||
|
x += x >> 4
|
||||||
|
x &= 0x0f0f0f0f0f0f0f0f
|
||||||
|
x *= 0x0101010101010101
|
||||||
|
return x >> 56
|
||||||
|
}
|
||||||
|
|
||||||
|
func popcntSliceGo(s []uint64) uint64 {
|
||||||
|
cnt := uint64(0)
|
||||||
|
for _, x := range s {
|
||||||
|
cnt += popcount(x)
|
||||||
|
}
|
||||||
|
return cnt
|
||||||
|
}
|
||||||
|
|
||||||
|
func popcntMaskSliceGo(s, m []uint64) uint64 {
|
||||||
|
cnt := uint64(0)
|
||||||
|
for i := range s {
|
||||||
|
cnt += popcount(s[i] &^ m[i])
|
||||||
|
}
|
||||||
|
return cnt
|
||||||
|
}
|
||||||
|
|
||||||
|
func popcntAndSliceGo(s, m []uint64) uint64 {
|
||||||
|
cnt := uint64(0)
|
||||||
|
for i := range s {
|
||||||
|
cnt += popcount(s[i] & m[i])
|
||||||
|
}
|
||||||
|
return cnt
|
||||||
|
}
|
||||||
|
|
||||||
|
func popcntOrSliceGo(s, m []uint64) uint64 {
|
||||||
|
cnt := uint64(0)
|
||||||
|
for i := range s {
|
||||||
|
cnt += popcount(s[i] | m[i])
|
||||||
|
}
|
||||||
|
return cnt
|
||||||
|
}
|
||||||
|
|
||||||
|
func popcntXorSliceGo(s, m []uint64) uint64 {
|
||||||
|
cnt := uint64(0)
|
||||||
|
for i := range s {
|
||||||
|
cnt += popcount(s[i] ^ m[i])
|
||||||
|
}
|
||||||
|
return cnt
|
||||||
|
}
|
||||||
45
vendor/github.com/bits-and-blooms/bitset/popcnt_19.go
generated
vendored
Normal file
45
vendor/github.com/bits-and-blooms/bitset/popcnt_19.go
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// +build go1.9
|
||||||
|
|
||||||
|
package bitset
|
||||||
|
|
||||||
|
import "math/bits"
|
||||||
|
|
||||||
|
func popcntSlice(s []uint64) uint64 {
|
||||||
|
var cnt int
|
||||||
|
for _, x := range s {
|
||||||
|
cnt += bits.OnesCount64(x)
|
||||||
|
}
|
||||||
|
return uint64(cnt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func popcntMaskSlice(s, m []uint64) uint64 {
|
||||||
|
var cnt int
|
||||||
|
for i := range s {
|
||||||
|
cnt += bits.OnesCount64(s[i] &^ m[i])
|
||||||
|
}
|
||||||
|
return uint64(cnt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func popcntAndSlice(s, m []uint64) uint64 {
|
||||||
|
var cnt int
|
||||||
|
for i := range s {
|
||||||
|
cnt += bits.OnesCount64(s[i] & m[i])
|
||||||
|
}
|
||||||
|
return uint64(cnt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func popcntOrSlice(s, m []uint64) uint64 {
|
||||||
|
var cnt int
|
||||||
|
for i := range s {
|
||||||
|
cnt += bits.OnesCount64(s[i] | m[i])
|
||||||
|
}
|
||||||
|
return uint64(cnt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func popcntXorSlice(s, m []uint64) uint64 {
|
||||||
|
var cnt int
|
||||||
|
for i := range s {
|
||||||
|
cnt += bits.OnesCount64(s[i] ^ m[i])
|
||||||
|
}
|
||||||
|
return uint64(cnt)
|
||||||
|
}
|
||||||
68
vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.go
generated
vendored
Normal file
68
vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.go
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// +build !go1.9
|
||||||
|
// +build amd64,!appengine
|
||||||
|
|
||||||
|
package bitset
|
||||||
|
|
||||||
|
// *** the following functions are defined in popcnt_amd64.s
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
|
||||||
|
func hasAsm() bool
|
||||||
|
|
||||||
|
// useAsm is a flag used to select the GO or ASM implementation of the popcnt function
|
||||||
|
var useAsm = hasAsm()
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
|
||||||
|
func popcntSliceAsm(s []uint64) uint64
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
|
||||||
|
func popcntMaskSliceAsm(s, m []uint64) uint64
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
|
||||||
|
func popcntAndSliceAsm(s, m []uint64) uint64
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
|
||||||
|
func popcntOrSliceAsm(s, m []uint64) uint64
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
|
||||||
|
func popcntXorSliceAsm(s, m []uint64) uint64
|
||||||
|
|
||||||
|
func popcntSlice(s []uint64) uint64 {
|
||||||
|
if useAsm {
|
||||||
|
return popcntSliceAsm(s)
|
||||||
|
}
|
||||||
|
return popcntSliceGo(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func popcntMaskSlice(s, m []uint64) uint64 {
|
||||||
|
if useAsm {
|
||||||
|
return popcntMaskSliceAsm(s, m)
|
||||||
|
}
|
||||||
|
return popcntMaskSliceGo(s, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func popcntAndSlice(s, m []uint64) uint64 {
|
||||||
|
if useAsm {
|
||||||
|
return popcntAndSliceAsm(s, m)
|
||||||
|
}
|
||||||
|
return popcntAndSliceGo(s, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func popcntOrSlice(s, m []uint64) uint64 {
|
||||||
|
if useAsm {
|
||||||
|
return popcntOrSliceAsm(s, m)
|
||||||
|
}
|
||||||
|
return popcntOrSliceGo(s, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func popcntXorSlice(s, m []uint64) uint64 {
|
||||||
|
if useAsm {
|
||||||
|
return popcntXorSliceAsm(s, m)
|
||||||
|
}
|
||||||
|
return popcntXorSliceGo(s, m)
|
||||||
|
}
|
||||||
104
vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.s
generated
vendored
Normal file
104
vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.s
generated
vendored
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
// +build !go1.9
|
||||||
|
// +build amd64,!appengine
|
||||||
|
|
||||||
|
TEXT ·hasAsm(SB),4,$0-1
|
||||||
|
MOVQ $1, AX
|
||||||
|
CPUID
|
||||||
|
SHRQ $23, CX
|
||||||
|
ANDQ $1, CX
|
||||||
|
MOVB CX, ret+0(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
#define POPCNTQ_DX_DX BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0xd2
|
||||||
|
|
||||||
|
TEXT ·popcntSliceAsm(SB),4,$0-32
|
||||||
|
XORQ AX, AX
|
||||||
|
MOVQ s+0(FP), SI
|
||||||
|
MOVQ s_len+8(FP), CX
|
||||||
|
TESTQ CX, CX
|
||||||
|
JZ popcntSliceEnd
|
||||||
|
popcntSliceLoop:
|
||||||
|
BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0x16 // POPCNTQ (SI), DX
|
||||||
|
ADDQ DX, AX
|
||||||
|
ADDQ $8, SI
|
||||||
|
LOOP popcntSliceLoop
|
||||||
|
popcntSliceEnd:
|
||||||
|
MOVQ AX, ret+24(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·popcntMaskSliceAsm(SB),4,$0-56
|
||||||
|
XORQ AX, AX
|
||||||
|
MOVQ s+0(FP), SI
|
||||||
|
MOVQ s_len+8(FP), CX
|
||||||
|
TESTQ CX, CX
|
||||||
|
JZ popcntMaskSliceEnd
|
||||||
|
MOVQ m+24(FP), DI
|
||||||
|
popcntMaskSliceLoop:
|
||||||
|
MOVQ (DI), DX
|
||||||
|
NOTQ DX
|
||||||
|
ANDQ (SI), DX
|
||||||
|
POPCNTQ_DX_DX
|
||||||
|
ADDQ DX, AX
|
||||||
|
ADDQ $8, SI
|
||||||
|
ADDQ $8, DI
|
||||||
|
LOOP popcntMaskSliceLoop
|
||||||
|
popcntMaskSliceEnd:
|
||||||
|
MOVQ AX, ret+48(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·popcntAndSliceAsm(SB),4,$0-56
|
||||||
|
XORQ AX, AX
|
||||||
|
MOVQ s+0(FP), SI
|
||||||
|
MOVQ s_len+8(FP), CX
|
||||||
|
TESTQ CX, CX
|
||||||
|
JZ popcntAndSliceEnd
|
||||||
|
MOVQ m+24(FP), DI
|
||||||
|
popcntAndSliceLoop:
|
||||||
|
MOVQ (DI), DX
|
||||||
|
ANDQ (SI), DX
|
||||||
|
POPCNTQ_DX_DX
|
||||||
|
ADDQ DX, AX
|
||||||
|
ADDQ $8, SI
|
||||||
|
ADDQ $8, DI
|
||||||
|
LOOP popcntAndSliceLoop
|
||||||
|
popcntAndSliceEnd:
|
||||||
|
MOVQ AX, ret+48(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·popcntOrSliceAsm(SB),4,$0-56
|
||||||
|
XORQ AX, AX
|
||||||
|
MOVQ s+0(FP), SI
|
||||||
|
MOVQ s_len+8(FP), CX
|
||||||
|
TESTQ CX, CX
|
||||||
|
JZ popcntOrSliceEnd
|
||||||
|
MOVQ m+24(FP), DI
|
||||||
|
popcntOrSliceLoop:
|
||||||
|
MOVQ (DI), DX
|
||||||
|
ORQ (SI), DX
|
||||||
|
POPCNTQ_DX_DX
|
||||||
|
ADDQ DX, AX
|
||||||
|
ADDQ $8, SI
|
||||||
|
ADDQ $8, DI
|
||||||
|
LOOP popcntOrSliceLoop
|
||||||
|
popcntOrSliceEnd:
|
||||||
|
MOVQ AX, ret+48(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·popcntXorSliceAsm(SB),4,$0-56
|
||||||
|
XORQ AX, AX
|
||||||
|
MOVQ s+0(FP), SI
|
||||||
|
MOVQ s_len+8(FP), CX
|
||||||
|
TESTQ CX, CX
|
||||||
|
JZ popcntXorSliceEnd
|
||||||
|
MOVQ m+24(FP), DI
|
||||||
|
popcntXorSliceLoop:
|
||||||
|
MOVQ (DI), DX
|
||||||
|
XORQ (SI), DX
|
||||||
|
POPCNTQ_DX_DX
|
||||||
|
ADDQ DX, AX
|
||||||
|
ADDQ $8, SI
|
||||||
|
ADDQ $8, DI
|
||||||
|
LOOP popcntXorSliceLoop
|
||||||
|
popcntXorSliceEnd:
|
||||||
|
MOVQ AX, ret+48(FP)
|
||||||
|
RET
|
||||||
24
vendor/github.com/bits-and-blooms/bitset/popcnt_generic.go
generated
vendored
Normal file
24
vendor/github.com/bits-and-blooms/bitset/popcnt_generic.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// +build !go1.9
|
||||||
|
// +build !amd64 appengine
|
||||||
|
|
||||||
|
package bitset
|
||||||
|
|
||||||
|
func popcntSlice(s []uint64) uint64 {
|
||||||
|
return popcntSliceGo(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func popcntMaskSlice(s, m []uint64) uint64 {
|
||||||
|
return popcntMaskSliceGo(s, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func popcntAndSlice(s, m []uint64) uint64 {
|
||||||
|
return popcntAndSliceGo(s, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func popcntOrSlice(s, m []uint64) uint64 {
|
||||||
|
return popcntOrSliceGo(s, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func popcntXorSlice(s, m []uint64) uint64 {
|
||||||
|
return popcntXorSliceGo(s, m)
|
||||||
|
}
|
||||||
14
vendor/github.com/bits-and-blooms/bitset/trailing_zeros_18.go
generated
vendored
Normal file
14
vendor/github.com/bits-and-blooms/bitset/trailing_zeros_18.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// +build !go1.9
|
||||||
|
|
||||||
|
package bitset
|
||||||
|
|
||||||
|
var deBruijn = [...]byte{
|
||||||
|
0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4,
|
||||||
|
62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5,
|
||||||
|
63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11,
|
||||||
|
54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
func trailingZeroes64(v uint64) uint {
|
||||||
|
return uint(deBruijn[((v&-v)*0x03f79d71b4ca8b09)>>58])
|
||||||
|
}
|
||||||
9
vendor/github.com/bits-and-blooms/bitset/trailing_zeros_19.go
generated
vendored
Normal file
9
vendor/github.com/bits-and-blooms/bitset/trailing_zeros_19.go
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// +build go1.9
|
||||||
|
|
||||||
|
package bitset
|
||||||
|
|
||||||
|
import "math/bits"
|
||||||
|
|
||||||
|
func trailingZeroes64(v uint64) uint {
|
||||||
|
return uint(bits.TrailingZeros64(v))
|
||||||
|
}
|
||||||
8
vendor/github.com/cyphar/filepath-securejoin/.travis.yml
generated
vendored
8
vendor/github.com/cyphar/filepath-securejoin/.travis.yml
generated
vendored
@ -4,12 +4,10 @@
|
|||||||
|
|
||||||
language: go
|
language: go
|
||||||
go:
|
go:
|
||||||
- 1.13.x
|
- 1.7.x
|
||||||
- 1.16.x
|
- 1.8.x
|
||||||
- tip
|
- tip
|
||||||
arch:
|
|
||||||
- AMD64
|
|
||||||
- ppc64le
|
|
||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
- osx
|
- osx
|
||||||
|
|||||||
20
vendor/github.com/cyphar/filepath-securejoin/README.md
generated
vendored
20
vendor/github.com/cyphar/filepath-securejoin/README.md
generated
vendored
@ -7,19 +7,6 @@ standard library][go#20126]. The purpose of this function is to be a "secure"
|
|||||||
alternative to `filepath.Join`, and in particular it provides certain
|
alternative to `filepath.Join`, and in particular it provides certain
|
||||||
guarantees that are not provided by `filepath.Join`.
|
guarantees that are not provided by `filepath.Join`.
|
||||||
|
|
||||||
> **NOTE**: This code is *only* safe if you are not at risk of other processes
|
|
||||||
> modifying path components after you've used `SecureJoin`. If it is possible
|
|
||||||
> for a malicious process to modify path components of the resolved path, then
|
|
||||||
> you will be vulnerable to some fairly trivial TOCTOU race conditions. [There
|
|
||||||
> are some Linux kernel patches I'm working on which might allow for a better
|
|
||||||
> solution.][lwn-obeneath]
|
|
||||||
>
|
|
||||||
> In addition, with a slightly modified API it might be possible to use
|
|
||||||
> `O_PATH` and verify that the opened path is actually the resolved one -- but
|
|
||||||
> I have not done that yet. I might add it in the future as a helper function
|
|
||||||
> to help users verify the path (we can't just return `/proc/self/fd/<foo>`
|
|
||||||
> because that doesn't always work transparently for all users).
|
|
||||||
|
|
||||||
This is the function prototype:
|
This is the function prototype:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@ -29,8 +16,8 @@ func SecureJoin(root, unsafePath string) (string, error)
|
|||||||
This library **guarantees** the following:
|
This library **guarantees** the following:
|
||||||
|
|
||||||
* If no error is set, the resulting string **must** be a child path of
|
* If no error is set, the resulting string **must** be a child path of
|
||||||
`root` and will not contain any symlink path components (they will all be
|
`SecureJoin` and will not contain any symlink path components (they will all
|
||||||
expanded).
|
be expanded).
|
||||||
|
|
||||||
* When expanding symlinks, all symlink path components **must** be resolved
|
* When expanding symlinks, all symlink path components **must** be resolved
|
||||||
relative to the provided root. In particular, this can be considered a
|
relative to the provided root. In particular, this can be considered a
|
||||||
@ -38,7 +25,7 @@ This library **guarantees** the following:
|
|||||||
these symlinks will **not** be expanded lexically (`filepath.Clean` is not
|
these symlinks will **not** be expanded lexically (`filepath.Clean` is not
|
||||||
called on the input before processing).
|
called on the input before processing).
|
||||||
|
|
||||||
* Non-existent path components are unaffected by `SecureJoin` (similar to
|
* Non-existant path components are unaffected by `SecureJoin` (similar to
|
||||||
`filepath.EvalSymlinks`'s semantics).
|
`filepath.EvalSymlinks`'s semantics).
|
||||||
|
|
||||||
* The returned path will always be `filepath.Clean`ed and thus not contain any
|
* The returned path will always be `filepath.Clean`ed and thus not contain any
|
||||||
@ -70,7 +57,6 @@ func SecureJoin(root, unsafePath string) (string, error) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
[lwn-obeneath]: https://lwn.net/Articles/767547/
|
|
||||||
[go#20126]: https://github.com/golang/go/issues/20126
|
[go#20126]: https://github.com/golang/go/issues/20126
|
||||||
|
|
||||||
### License ###
|
### License ###
|
||||||
|
|||||||
2
vendor/github.com/cyphar/filepath-securejoin/VERSION
generated
vendored
2
vendor/github.com/cyphar/filepath-securejoin/VERSION
generated
vendored
@ -1 +1 @@
|
|||||||
0.2.3
|
0.2.2
|
||||||
|
|||||||
25
vendor/github.com/cyphar/filepath-securejoin/join.go
generated
vendored
25
vendor/github.com/cyphar/filepath-securejoin/join.go
generated
vendored
@ -12,20 +12,39 @@ package securejoin
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrSymlinkLoop is returned by SecureJoinVFS when too many symlinks have been
|
||||||
|
// evaluated in attempting to securely join the two given paths.
|
||||||
|
var ErrSymlinkLoop = errors.Wrap(syscall.ELOOP, "secure join")
|
||||||
|
|
||||||
// IsNotExist tells you if err is an error that implies that either the path
|
// IsNotExist tells you if err is an error that implies that either the path
|
||||||
// accessed does not exist (or path components don't exist). This is
|
// accessed does not exist (or path components don't exist). This is
|
||||||
// effectively a more broad version of os.IsNotExist.
|
// effectively a more broad version of os.IsNotExist.
|
||||||
func IsNotExist(err error) bool {
|
func IsNotExist(err error) bool {
|
||||||
|
// If it's a bone-fide ENOENT just bail.
|
||||||
|
if os.IsNotExist(errors.Cause(err)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Check that it's not actually an ENOTDIR, which in some cases is a more
|
// Check that it's not actually an ENOTDIR, which in some cases is a more
|
||||||
// convoluted case of ENOENT (usually involving weird paths).
|
// convoluted case of ENOENT (usually involving weird paths).
|
||||||
return errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) || errors.Is(err, syscall.ENOENT)
|
var errno error
|
||||||
|
switch err := errors.Cause(err).(type) {
|
||||||
|
case *os.PathError:
|
||||||
|
errno = err.Err
|
||||||
|
case *os.LinkError:
|
||||||
|
errno = err.Err
|
||||||
|
case *os.SyscallError:
|
||||||
|
errno = err.Err
|
||||||
|
}
|
||||||
|
return errno == syscall.ENOTDIR || errno == syscall.ENOENT
|
||||||
}
|
}
|
||||||
|
|
||||||
// SecureJoinVFS joins the two given path components (similar to Join) except
|
// SecureJoinVFS joins the two given path components (similar to Join) except
|
||||||
@ -49,7 +68,7 @@ func SecureJoinVFS(root, unsafePath string, vfs VFS) (string, error) {
|
|||||||
n := 0
|
n := 0
|
||||||
for unsafePath != "" {
|
for unsafePath != "" {
|
||||||
if n > 255 {
|
if n > 255 {
|
||||||
return "", &os.PathError{Op: "SecureJoin", Path: root + "/" + unsafePath, Err: syscall.ELOOP}
|
return "", ErrSymlinkLoop
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next path component, p.
|
// Next path component, p.
|
||||||
|
|||||||
1
vendor/github.com/cyphar/filepath-securejoin/vendor.conf
generated
vendored
Normal file
1
vendor/github.com/cyphar/filepath-securejoin/vendor.conf
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
github.com/pkg/errors v0.8.0
|
||||||
29
vendor/github.com/docker/distribution/reference/normalize.go
generated
vendored
29
vendor/github.com/docker/distribution/reference/normalize.go
generated
vendored
@ -56,35 +56,6 @@ func ParseNormalizedNamed(s string) (Named, error) {
|
|||||||
return named, nil
|
return named, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseDockerRef normalizes the image reference following the docker convention. This is added
|
|
||||||
// mainly for backward compatibility.
|
|
||||||
// The reference returned can only be either tagged or digested. For reference contains both tag
|
|
||||||
// and digest, the function returns digested reference, e.g. docker.io/library/busybox:latest@
|
|
||||||
// sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa will be returned as
|
|
||||||
// docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa.
|
|
||||||
func ParseDockerRef(ref string) (Named, error) {
|
|
||||||
named, err := ParseNormalizedNamed(ref)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if _, ok := named.(NamedTagged); ok {
|
|
||||||
if canonical, ok := named.(Canonical); ok {
|
|
||||||
// The reference is both tagged and digested, only
|
|
||||||
// return digested.
|
|
||||||
newNamed, err := WithName(canonical.Name())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
newCanonical, err := WithDigest(newNamed, canonical.Digest())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return newCanonical, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TagNameOnly(named), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// splitDockerDomain splits a repository name to domain and remotename string.
|
// splitDockerDomain splits a repository name to domain and remotename string.
|
||||||
// If no valid domain is found, the default domain is used. Repository name
|
// If no valid domain is found, the default domain is used. Repository name
|
||||||
// needs to be already validated before.
|
// needs to be already validated before.
|
||||||
|
|||||||
2
vendor/github.com/docker/distribution/reference/reference.go
generated
vendored
2
vendor/github.com/docker/distribution/reference/reference.go
generated
vendored
@ -205,7 +205,7 @@ func Parse(s string) (Reference, error) {
|
|||||||
var repo repository
|
var repo repository
|
||||||
|
|
||||||
nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1])
|
nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1])
|
||||||
if len(nameMatch) == 3 {
|
if nameMatch != nil && len(nameMatch) == 3 {
|
||||||
repo.domain = nameMatch[1]
|
repo.domain = nameMatch[1]
|
||||||
repo.path = nameMatch[2]
|
repo.path = nameMatch[2]
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
5
vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go
generated
vendored
5
vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go
generated
vendored
@ -3,6 +3,7 @@ package apparmor
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ var (
|
|||||||
func isEnabled() bool {
|
func isEnabled() bool {
|
||||||
checkAppArmor.Do(func() {
|
checkAppArmor.Do(func() {
|
||||||
if _, err := os.Stat("/sys/kernel/security/apparmor"); err == nil {
|
if _, err := os.Stat("/sys/kernel/security/apparmor"); err == nil {
|
||||||
buf, err := os.ReadFile("/sys/module/apparmor/parameters/enabled")
|
buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled")
|
||||||
appArmorEnabled = err == nil && len(buf) > 1 && buf[0] == 'Y'
|
appArmorEnabled = err == nil && len(buf) > 1 && buf[0] == 'Y'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -51,7 +52,7 @@ func setProcAttr(attr, value string) error {
|
|||||||
// changeOnExec reimplements aa_change_onexec from libapparmor in Go
|
// changeOnExec reimplements aa_change_onexec from libapparmor in Go
|
||||||
func changeOnExec(name string) error {
|
func changeOnExec(name string) error {
|
||||||
if err := setProcAttr("exec", "exec "+name); err != nil {
|
if err := setProcAttr("exec", "exec "+name); err != nil {
|
||||||
return fmt.Errorf("apparmor failed to apply profile: %w", err)
|
return fmt.Errorf("apparmor failed to apply profile: %s", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
1
vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_unsupported.go
generated
vendored
1
vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_unsupported.go
generated
vendored
@ -1,4 +1,3 @@
|
|||||||
//go:build !linux
|
|
||||||
// +build !linux
|
// +build !linux
|
||||||
|
|
||||||
package apparmor
|
package apparmor
|
||||||
|
|||||||
11
vendor/github.com/opencontainers/runc/libcontainer/utils/cmsg.go
generated
vendored
11
vendor/github.com/opencontainers/runc/libcontainer/utils/cmsg.go
generated
vendored
@ -1,3 +1,5 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -86,11 +88,6 @@ func SendFd(socket *os.File, name string, fd uintptr) error {
|
|||||||
if len(name) >= MaxNameLen {
|
if len(name) >= MaxNameLen {
|
||||||
return fmt.Errorf("sendfd: filename too long: %s", name)
|
return fmt.Errorf("sendfd: filename too long: %s", name)
|
||||||
}
|
}
|
||||||
return SendFds(socket, []byte(name), int(fd))
|
oob := unix.UnixRights(int(fd))
|
||||||
}
|
return unix.Sendmsg(int(socket.Fd()), []byte(name), oob, nil, 0)
|
||||||
|
|
||||||
// SendFds sends a list of files descriptor and msg over the given AF_UNIX socket.
|
|
||||||
func SendFds(socket *os.File, msg []byte, fds ...int) error {
|
|
||||||
oob := unix.UnixRights(fds...)
|
|
||||||
return unix.Sendmsg(int(socket.Fd()), msg, oob, nil, 0)
|
|
||||||
}
|
}
|
||||||
|
|||||||
14
vendor/github.com/opencontainers/runc/libcontainer/utils/utils.go
generated
vendored
14
vendor/github.com/opencontainers/runc/libcontainer/utils/utils.go
generated
vendored
@ -11,7 +11,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
securejoin "github.com/cyphar/filepath-securejoin"
|
"github.com/cyphar/filepath-securejoin"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,6 +33,16 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResolveRootfs ensures that the current working directory is
|
||||||
|
// not a symlink and returns the absolute path to the rootfs
|
||||||
|
func ResolveRootfs(uncleanRootfs string) (string, error) {
|
||||||
|
rootfs, err := filepath.Abs(uncleanRootfs)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return filepath.EvalSymlinks(rootfs)
|
||||||
|
}
|
||||||
|
|
||||||
// ExitStatus returns the correct exit status for a process based on if it
|
// ExitStatus returns the correct exit status for a process based on if it
|
||||||
// was signaled or exited cleanly
|
// was signaled or exited cleanly
|
||||||
func ExitStatus(status unix.WaitStatus) int {
|
func ExitStatus(status unix.WaitStatus) int {
|
||||||
@ -110,7 +120,7 @@ func WithProcfd(root, unsafePath string, fn func(procfd string) error) error {
|
|||||||
unsafePath = stripRoot(root, unsafePath)
|
unsafePath = stripRoot(root, unsafePath)
|
||||||
path, err := securejoin.SecureJoin(root, unsafePath)
|
path, err := securejoin.SecureJoin(root, unsafePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("resolving path inside rootfs failed: %w", err)
|
return fmt.Errorf("resolving path inside rootfs failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open the target path.
|
// Open the target path.
|
||||||
|
|||||||
5
vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go
generated
vendored
5
vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go
generated
vendored
@ -1,4 +1,3 @@
|
|||||||
//go:build !windows
|
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package utils
|
package utils
|
||||||
@ -15,7 +14,7 @@ import (
|
|||||||
func EnsureProcHandle(fh *os.File) error {
|
func EnsureProcHandle(fh *os.File) error {
|
||||||
var buf unix.Statfs_t
|
var buf unix.Statfs_t
|
||||||
if err := unix.Fstatfs(int(fh.Fd()), &buf); err != nil {
|
if err := unix.Fstatfs(int(fh.Fd()), &buf); err != nil {
|
||||||
return fmt.Errorf("ensure %s is on procfs: %w", fh.Name(), err)
|
return fmt.Errorf("ensure %s is on procfs: %v", fh.Name(), err)
|
||||||
}
|
}
|
||||||
if buf.Type != unix.PROC_SUPER_MAGIC {
|
if buf.Type != unix.PROC_SUPER_MAGIC {
|
||||||
return fmt.Errorf("%s is not on procfs", fh.Name())
|
return fmt.Errorf("%s is not on procfs", fh.Name())
|
||||||
@ -53,7 +52,7 @@ func CloseExecFrom(minFd int) error {
|
|||||||
// Intentionally ignore errors from unix.CloseOnExec -- the cases where
|
// Intentionally ignore errors from unix.CloseOnExec -- the cases where
|
||||||
// this might fail are basically file descriptors that have already
|
// this might fail are basically file descriptors that have already
|
||||||
// been closed (including and especially the one that was created when
|
// been closed (including and especially the one that was created when
|
||||||
// os.ReadDir did the "opendir" syscall).
|
// ioutil.ReadDir did the "opendir" syscall).
|
||||||
unix.CloseOnExec(fd)
|
unix.CloseOnExec(fd)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
22
vendor/github.com/opencontainers/selinux/go-selinux/rchcon.go
generated
vendored
22
vendor/github.com/opencontainers/selinux/go-selinux/rchcon.go
generated
vendored
@ -1,22 +0,0 @@
|
|||||||
// +build linux,go1.16
|
|
||||||
|
|
||||||
package selinux
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io/fs"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/opencontainers/selinux/pkg/pwalkdir"
|
|
||||||
)
|
|
||||||
|
|
||||||
func rchcon(fpath, label string) error {
|
|
||||||
return pwalkdir.Walk(fpath, func(p string, _ fs.DirEntry, _ error) error {
|
|
||||||
e := setFileLabel(p, label)
|
|
||||||
// Walk a file tree can race with removal, so ignore ENOENT.
|
|
||||||
if errors.Is(e, os.ErrNotExist) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return e
|
|
||||||
})
|
|
||||||
}
|
|
||||||
21
vendor/github.com/opencontainers/selinux/go-selinux/rchcon_go115.go
generated
vendored
21
vendor/github.com/opencontainers/selinux/go-selinux/rchcon_go115.go
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
// +build linux,!go1.16
|
|
||||||
|
|
||||||
package selinux
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/opencontainers/selinux/pkg/pwalk"
|
|
||||||
)
|
|
||||||
|
|
||||||
func rchcon(fpath, label string) error {
|
|
||||||
return pwalk.Walk(fpath, func(p string, _ os.FileInfo, _ error) error {
|
|
||||||
e := setFileLabel(p, label)
|
|
||||||
// Walk a file tree can race with removal, so ignore ENOENT.
|
|
||||||
if errors.Is(e, os.ErrNotExist) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return e
|
|
||||||
})
|
|
||||||
}
|
|
||||||
26
vendor/github.com/opencontainers/selinux/go-selinux/selinux.go
generated
vendored
26
vendor/github.com/opencontainers/selinux/go-selinux/selinux.go
generated
vendored
@ -1,7 +1,7 @@
|
|||||||
package selinux
|
package selinux
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -38,8 +38,6 @@ var (
|
|||||||
|
|
||||||
// CategoryRange allows the upper bound on the category range to be adjusted
|
// CategoryRange allows the upper bound on the category range to be adjusted
|
||||||
CategoryRange = DefaultCategoryRange
|
CategoryRange = DefaultCategoryRange
|
||||||
|
|
||||||
privContainerMountLabel string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Context is a representation of the SELinux label broken into 4 parts
|
// Context is a representation of the SELinux label broken into 4 parts
|
||||||
@ -61,30 +59,16 @@ func ClassIndex(class string) (int, error) {
|
|||||||
return classIndex(class)
|
return classIndex(class)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetFileLabel sets the SELinux label for this path, following symlinks,
|
// SetFileLabel sets the SELinux label for this path or returns an error.
|
||||||
// or returns an error.
|
|
||||||
func SetFileLabel(fpath string, label string) error {
|
func SetFileLabel(fpath string, label string) error {
|
||||||
return setFileLabel(fpath, label)
|
return setFileLabel(fpath, label)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LsetFileLabel sets the SELinux label for this path, not following symlinks,
|
// FileLabel returns the SELinux label for this path or returns an error.
|
||||||
// or returns an error.
|
|
||||||
func LsetFileLabel(fpath string, label string) error {
|
|
||||||
return lSetFileLabel(fpath, label)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FileLabel returns the SELinux label for this path, following symlinks,
|
|
||||||
// or returns an error.
|
|
||||||
func FileLabel(fpath string) (string, error) {
|
func FileLabel(fpath string) (string, error) {
|
||||||
return fileLabel(fpath)
|
return fileLabel(fpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LfileLabel returns the SELinux label for this path, not following symlinks,
|
|
||||||
// or returns an error.
|
|
||||||
func LfileLabel(fpath string) (string, error) {
|
|
||||||
return lFileLabel(fpath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetFSCreateLabel tells the kernel what label to use for all file system objects
|
// SetFSCreateLabel tells the kernel what label to use for all file system objects
|
||||||
// created by this task.
|
// created by this task.
|
||||||
// Set the label to an empty string to return to the default label. Calls to SetFSCreateLabel
|
// Set the label to an empty string to return to the default label. Calls to SetFSCreateLabel
|
||||||
@ -269,8 +253,6 @@ func CopyLevel(src, dest string) (string, error) {
|
|||||||
// Chcon changes the fpath file object to the SELinux label label.
|
// Chcon changes the fpath file object to the SELinux label label.
|
||||||
// If fpath is a directory and recurse is true, then Chcon walks the
|
// If fpath is a directory and recurse is true, then Chcon walks the
|
||||||
// directory tree setting the label.
|
// directory tree setting the label.
|
||||||
//
|
|
||||||
// The fpath itself is guaranteed to be relabeled last.
|
|
||||||
func Chcon(fpath string, label string, recurse bool) error {
|
func Chcon(fpath string, label string, recurse bool) error {
|
||||||
return chcon(fpath, label, recurse)
|
return chcon(fpath, label, recurse)
|
||||||
}
|
}
|
||||||
@ -298,7 +280,5 @@ func GetDefaultContextWithLevel(user, level, scon string) (string, error) {
|
|||||||
|
|
||||||
// PrivContainerMountLabel returns mount label for privileged containers
|
// PrivContainerMountLabel returns mount label for privileged containers
|
||||||
func PrivContainerMountLabel() string {
|
func PrivContainerMountLabel() string {
|
||||||
// Make sure label is initialized.
|
|
||||||
_ = label("")
|
|
||||||
return privContainerMountLabel
|
return privContainerMountLabel
|
||||||
}
|
}
|
||||||
|
|||||||
282
vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
generated
vendored
282
vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
generated
vendored
@ -5,18 +5,20 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/big"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/bits-and-blooms/bitset"
|
||||||
|
"github.com/opencontainers/selinux/pkg/pwalk"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,6 +35,8 @@ const (
|
|||||||
xattrNameSelinux = "security.selinux"
|
xattrNameSelinux = "security.selinux"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var policyRoot = filepath.Join(selinuxDir, readConfig(selinuxTypeTag))
|
||||||
|
|
||||||
type selinuxState struct {
|
type selinuxState struct {
|
||||||
enabledSet bool
|
enabledSet bool
|
||||||
enabled bool
|
enabled bool
|
||||||
@ -44,7 +48,7 @@ type selinuxState struct {
|
|||||||
|
|
||||||
type level struct {
|
type level struct {
|
||||||
sens uint
|
sens uint
|
||||||
cats *big.Int
|
cats *bitset.BitSet
|
||||||
}
|
}
|
||||||
|
|
||||||
type mlsRange struct {
|
type mlsRange struct {
|
||||||
@ -67,6 +71,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`)
|
||||||
readOnlyFileLabel string
|
readOnlyFileLabel string
|
||||||
state = selinuxState{
|
state = selinuxState{
|
||||||
mcsList: make(map[string]bool),
|
mcsList: make(map[string]bool),
|
||||||
@ -75,24 +80,8 @@ var (
|
|||||||
// for attrPath()
|
// for attrPath()
|
||||||
attrPathOnce sync.Once
|
attrPathOnce sync.Once
|
||||||
haveThreadSelf bool
|
haveThreadSelf bool
|
||||||
|
|
||||||
// for policyRoot()
|
|
||||||
policyRootOnce sync.Once
|
|
||||||
policyRootVal string
|
|
||||||
|
|
||||||
// for label()
|
|
||||||
loadLabelsOnce sync.Once
|
|
||||||
labels map[string]string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func policyRoot() string {
|
|
||||||
policyRootOnce.Do(func() {
|
|
||||||
policyRootVal = filepath.Join(selinuxDir, readConfig(selinuxTypeTag))
|
|
||||||
})
|
|
||||||
|
|
||||||
return policyRootVal
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *selinuxState) setEnable(enabled bool) bool {
|
func (s *selinuxState) setEnable(enabled bool) bool {
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
@ -131,7 +120,7 @@ func verifySELinuxfsMount(mnt string) bool {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err == unix.EAGAIN || err == unix.EINTR { //nolint:errorlint // unix errors are bare
|
if err == unix.EAGAIN || err == unix.EINTR {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -234,7 +223,7 @@ func readConfig(target string) string {
|
|||||||
scanner := bufio.NewScanner(in)
|
scanner := bufio.NewScanner(in)
|
||||||
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
line := bytes.TrimSpace(scanner.Bytes())
|
line := strings.TrimSpace(scanner.Text())
|
||||||
if len(line) == 0 {
|
if len(line) == 0 {
|
||||||
// Skip blank lines
|
// Skip blank lines
|
||||||
continue
|
continue
|
||||||
@ -243,12 +232,11 @@ func readConfig(target string) string {
|
|||||||
// Skip comments
|
// Skip comments
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fields := bytes.SplitN(line, []byte{'='}, 2)
|
if groups := assignRegex.FindStringSubmatch(line); groups != nil {
|
||||||
if len(fields) != 2 {
|
key, val := strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2])
|
||||||
continue
|
if key == target {
|
||||||
|
return strings.Trim(val, "\"")
|
||||||
}
|
}
|
||||||
if bytes.Equal(fields[0], []byte(target)) {
|
|
||||||
return string(bytes.Trim(fields[1], `"`))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
@ -262,12 +250,12 @@ func isProcHandle(fh *os.File) error {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err != unix.EINTR { //nolint:errorlint // unix errors are bare
|
if err != unix.EINTR {
|
||||||
return &os.PathError{Op: "fstatfs", Path: fh.Name(), Err: err}
|
return errors.Wrapf(err, "statfs(%q) failed", fh.Name())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if buf.Type != unix.PROC_SUPER_MAGIC {
|
if buf.Type != unix.PROC_SUPER_MAGIC {
|
||||||
return fmt.Errorf("file %q is not on procfs", fh.Name())
|
return errors.Errorf("file %q is not on procfs", fh.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -287,15 +275,12 @@ func readCon(fpath string) (string, error) {
|
|||||||
if err := isProcHandle(in); err != nil {
|
if err := isProcHandle(in); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return readConFd(in)
|
|
||||||
}
|
|
||||||
|
|
||||||
func readConFd(in *os.File) (string, error) {
|
var retval string
|
||||||
data, err := ioutil.ReadAll(in)
|
if _, err := fmt.Fscanf(in, "%s", &retval); err != nil {
|
||||||
if err != nil {
|
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return string(bytes.TrimSuffix(data, []byte{0})), nil
|
return strings.Trim(retval, "\x00"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// classIndex returns the int index for an object class in the loaded policy,
|
// classIndex returns the int index for an object class in the loaded policy,
|
||||||
@ -316,9 +301,8 @@ func classIndex(class string) (int, error) {
|
|||||||
return index, nil
|
return index, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// lSetFileLabel sets the SELinux label for this path, not following symlinks,
|
// setFileLabel sets the SELinux label for this path or returns an error.
|
||||||
// or returns an error.
|
func setFileLabel(fpath string, label string) error {
|
||||||
func lSetFileLabel(fpath string, label string) error {
|
|
||||||
if fpath == "" {
|
if fpath == "" {
|
||||||
return ErrEmptyPath
|
return ErrEmptyPath
|
||||||
}
|
}
|
||||||
@ -327,61 +311,23 @@ func lSetFileLabel(fpath string, label string) error {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err != unix.EINTR { //nolint:errorlint // unix errors are bare
|
if err != unix.EINTR {
|
||||||
return &os.PathError{Op: "lsetxattr", Path: fpath, Err: err}
|
return errors.Wrapf(err, "failed to set file label on %s", fpath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// setFileLabel sets the SELinux label for this path, following symlinks,
|
// fileLabel returns the SELinux label for this path or returns an error.
|
||||||
// or returns an error.
|
|
||||||
func setFileLabel(fpath string, label string) error {
|
|
||||||
if fpath == "" {
|
|
||||||
return ErrEmptyPath
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
err := unix.Setxattr(fpath, xattrNameSelinux, []byte(label), 0)
|
|
||||||
if err == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if err != unix.EINTR { //nolint:errorlint // unix errors are bare
|
|
||||||
return &os.PathError{Op: "setxattr", Path: fpath, Err: err}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// fileLabel returns the SELinux label for this path, following symlinks,
|
|
||||||
// or returns an error.
|
|
||||||
func fileLabel(fpath string) (string, error) {
|
func fileLabel(fpath string) (string, error) {
|
||||||
if fpath == "" {
|
if fpath == "" {
|
||||||
return "", ErrEmptyPath
|
return "", ErrEmptyPath
|
||||||
}
|
}
|
||||||
|
|
||||||
label, err := getxattr(fpath, xattrNameSelinux)
|
|
||||||
if err != nil {
|
|
||||||
return "", &os.PathError{Op: "getxattr", Path: fpath, Err: err}
|
|
||||||
}
|
|
||||||
// Trim the NUL byte at the end of the byte buffer, if present.
|
|
||||||
if len(label) > 0 && label[len(label)-1] == '\x00' {
|
|
||||||
label = label[:len(label)-1]
|
|
||||||
}
|
|
||||||
return string(label), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// lFileLabel returns the SELinux label for this path, not following symlinks,
|
|
||||||
// or returns an error.
|
|
||||||
func lFileLabel(fpath string) (string, error) {
|
|
||||||
if fpath == "" {
|
|
||||||
return "", ErrEmptyPath
|
|
||||||
}
|
|
||||||
|
|
||||||
label, err := lgetxattr(fpath, xattrNameSelinux)
|
label, err := lgetxattr(fpath, xattrNameSelinux)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", &os.PathError{Op: "lgetxattr", Path: fpath, Err: err}
|
return "", err
|
||||||
}
|
}
|
||||||
// Trim the NUL byte at the end of the byte buffer, if present.
|
// Trim the NUL byte at the end of the byte buffer, if present.
|
||||||
if len(label) > 0 && label[len(label)-1] == '\x00' {
|
if len(label) > 0 && label[len(label)-1] == '\x00' {
|
||||||
@ -444,7 +390,7 @@ func writeCon(fpath, val string) error {
|
|||||||
_, err = out.Write(nil)
|
_, err = out.Write(nil)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.Wrapf(err, "failed to set %s on procfs", fpath)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -494,8 +440,8 @@ func computeCreateContext(source string, target string, class string) (string, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
// catsToBitset stores categories in a bitset.
|
// catsToBitset stores categories in a bitset.
|
||||||
func catsToBitset(cats string) (*big.Int, error) {
|
func catsToBitset(cats string) (*bitset.BitSet, error) {
|
||||||
bitset := new(big.Int)
|
bitset := &bitset.BitSet{}
|
||||||
|
|
||||||
catlist := strings.Split(cats, ",")
|
catlist := strings.Split(cats, ",")
|
||||||
for _, r := range catlist {
|
for _, r := range catlist {
|
||||||
@ -510,14 +456,14 @@ func catsToBitset(cats string) (*big.Int, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for i := catstart; i <= catend; i++ {
|
for i := catstart; i <= catend; i++ {
|
||||||
bitset.SetBit(bitset, int(i), 1)
|
bitset.Set(i)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cat, err := parseLevelItem(ranges[0], category)
|
cat, err := parseLevelItem(ranges[0], category)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
bitset.SetBit(bitset, int(cat), 1)
|
bitset.Set(cat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,13 +489,13 @@ func (l *level) parseLevel(levelStr string) error {
|
|||||||
lvl := strings.SplitN(levelStr, ":", 2)
|
lvl := strings.SplitN(levelStr, ":", 2)
|
||||||
sens, err := parseLevelItem(lvl[0], sensitivity)
|
sens, err := parseLevelItem(lvl[0], sensitivity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to parse sensitivity: %w", err)
|
return errors.Wrap(err, "failed to parse sensitivity")
|
||||||
}
|
}
|
||||||
l.sens = sens
|
l.sens = sens
|
||||||
if len(lvl) > 1 {
|
if len(lvl) > 1 {
|
||||||
cats, err := catsToBitset(lvl[1])
|
cats, err := catsToBitset(lvl[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to parse categories: %w", err)
|
return errors.Wrap(err, "failed to parse categories")
|
||||||
}
|
}
|
||||||
l.cats = cats
|
l.cats = cats
|
||||||
}
|
}
|
||||||
@ -567,14 +513,14 @@ func rangeStrToMLSRange(rangeStr string) (*mlsRange, error) {
|
|||||||
case 2:
|
case 2:
|
||||||
mlsRange.high = &level{}
|
mlsRange.high = &level{}
|
||||||
if err := mlsRange.high.parseLevel(levelSlice[1]); err != nil {
|
if err := mlsRange.high.parseLevel(levelSlice[1]); err != nil {
|
||||||
return nil, fmt.Errorf("failed to parse high level %q: %w", levelSlice[1], err)
|
return nil, errors.Wrapf(err, "failed to parse high level %q", levelSlice[1])
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
// rangeStr that is single level, e.g. s6:c0,c3,c5,c30.c1023
|
// rangeStr that is single level, e.g. s6:c0,c3,c5,c30.c1023
|
||||||
case 1:
|
case 1:
|
||||||
mlsRange.low = &level{}
|
mlsRange.low = &level{}
|
||||||
if err := mlsRange.low.parseLevel(levelSlice[0]); err != nil {
|
if err := mlsRange.low.parseLevel(levelSlice[0]); err != nil {
|
||||||
return nil, fmt.Errorf("failed to parse low level %q: %w", levelSlice[0], err)
|
return nil, errors.Wrapf(err, "failed to parse low level %q", levelSlice[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,30 +533,37 @@ func rangeStrToMLSRange(rangeStr string) (*mlsRange, error) {
|
|||||||
|
|
||||||
// bitsetToStr takes a category bitset and returns it in the
|
// bitsetToStr takes a category bitset and returns it in the
|
||||||
// canonical selinux syntax
|
// canonical selinux syntax
|
||||||
func bitsetToStr(c *big.Int) string {
|
func bitsetToStr(c *bitset.BitSet) string {
|
||||||
var str string
|
var str string
|
||||||
|
i, e := c.NextSet(0)
|
||||||
length := 0
|
len := 0
|
||||||
for i := int(c.TrailingZeroBits()); i < c.BitLen(); i++ {
|
for e {
|
||||||
if c.Bit(i) == 0 {
|
if len == 0 {
|
||||||
continue
|
|
||||||
}
|
|
||||||
if length == 0 {
|
|
||||||
if str != "" {
|
if str != "" {
|
||||||
str += ","
|
str += ","
|
||||||
}
|
}
|
||||||
str += "c" + strconv.Itoa(i)
|
str += "c" + strconv.Itoa(int(i))
|
||||||
}
|
}
|
||||||
if c.Bit(i+1) == 1 {
|
|
||||||
length++
|
next, e := c.NextSet(i + 1)
|
||||||
|
if e {
|
||||||
|
// consecutive cats
|
||||||
|
if next == i+1 {
|
||||||
|
len++
|
||||||
|
i = next
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if length == 1 {
|
|
||||||
str += ",c" + strconv.Itoa(i)
|
|
||||||
} else if length > 1 {
|
|
||||||
str += ".c" + strconv.Itoa(i)
|
|
||||||
}
|
}
|
||||||
length = 0
|
if len == 1 {
|
||||||
|
str += ",c" + strconv.Itoa(int(i))
|
||||||
|
} else if len > 1 {
|
||||||
|
str += ".c" + strconv.Itoa(int(i))
|
||||||
|
}
|
||||||
|
if !e {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
len = 0
|
||||||
|
i = next
|
||||||
}
|
}
|
||||||
|
|
||||||
return str
|
return str
|
||||||
@ -623,16 +576,13 @@ func (l1 *level) equal(l2 *level) bool {
|
|||||||
if l1.sens != l2.sens {
|
if l1.sens != l2.sens {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if l2.cats == nil || l1.cats == nil {
|
return l1.cats.Equal(l2.cats)
|
||||||
return l2.cats == l1.cats
|
|
||||||
}
|
|
||||||
return l1.cats.Cmp(l2.cats) == 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns an mlsRange as a string.
|
// String returns an mlsRange as a string.
|
||||||
func (m mlsRange) String() string {
|
func (m mlsRange) String() string {
|
||||||
low := "s" + strconv.Itoa(int(m.low.sens))
|
low := "s" + strconv.Itoa(int(m.low.sens))
|
||||||
if m.low.cats != nil && m.low.cats.BitLen() > 0 {
|
if m.low.cats != nil && m.low.cats.Count() > 0 {
|
||||||
low += ":" + bitsetToStr(m.low.cats)
|
low += ":" + bitsetToStr(m.low.cats)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -641,7 +591,7 @@ func (m mlsRange) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
high := "s" + strconv.Itoa(int(m.high.sens))
|
high := "s" + strconv.Itoa(int(m.high.sens))
|
||||||
if m.high.cats != nil && m.high.cats.BitLen() > 0 {
|
if m.high.cats != nil && m.high.cats.Count() > 0 {
|
||||||
high += ":" + bitsetToStr(m.high.cats)
|
high += ":" + bitsetToStr(m.high.cats)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -691,12 +641,10 @@ func calculateGlbLub(sourceRange, targetRange string) (string, error) {
|
|||||||
|
|
||||||
/* find the intersecting categories */
|
/* find the intersecting categories */
|
||||||
if s.low.cats != nil && t.low.cats != nil {
|
if s.low.cats != nil && t.low.cats != nil {
|
||||||
outrange.low.cats = new(big.Int)
|
outrange.low.cats = s.low.cats.Intersection(t.low.cats)
|
||||||
outrange.low.cats.And(s.low.cats, t.low.cats)
|
|
||||||
}
|
}
|
||||||
if s.high.cats != nil && t.high.cats != nil {
|
if s.high.cats != nil && t.high.cats != nil {
|
||||||
outrange.high.cats = new(big.Int)
|
outrange.high.cats = s.high.cats.Intersection(t.high.cats)
|
||||||
outrange.high.cats.And(s.high.cats, t.high.cats)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return outrange.String(), nil
|
return outrange.String(), nil
|
||||||
@ -717,7 +665,11 @@ func readWriteCon(fpath string, val string) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return readConFd(f)
|
var retval string
|
||||||
|
if _, err := fmt.Fscanf(f, "%s", &retval); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strings.Trim(retval, "\x00"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// setExecLabel sets the SELinux label that the kernel will use for any programs
|
// setExecLabel sets the SELinux label that the kernel will use for any programs
|
||||||
@ -745,21 +697,17 @@ func socketLabel() (string, error) {
|
|||||||
|
|
||||||
// peerLabel retrieves the label of the client on the other side of a socket
|
// peerLabel retrieves the label of the client on the other side of a socket
|
||||||
func peerLabel(fd uintptr) (string, error) {
|
func peerLabel(fd uintptr) (string, error) {
|
||||||
label, err := unix.GetsockoptString(int(fd), unix.SOL_SOCKET, unix.SO_PEERSEC)
|
return unix.GetsockoptString(int(fd), unix.SOL_SOCKET, unix.SO_PEERSEC)
|
||||||
if err != nil {
|
|
||||||
return "", &os.PathError{Op: "getsockopt", Path: "fd " + strconv.Itoa(int(fd)), Err: err}
|
|
||||||
}
|
|
||||||
return label, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// setKeyLabel takes a process label and tells the kernel to assign the
|
// setKeyLabel takes a process label and tells the kernel to assign the
|
||||||
// label to the next kernel keyring that gets created
|
// label to the next kernel keyring that gets created
|
||||||
func setKeyLabel(label string) error {
|
func setKeyLabel(label string) error {
|
||||||
err := writeCon("/proc/self/attr/keycreate", label)
|
err := writeCon("/proc/self/attr/keycreate", label)
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
if os.IsNotExist(errors.Cause(err)) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if label == "" && errors.Is(err, os.ErrPermission) {
|
if label == "" && os.IsPermission(errors.Cause(err)) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -772,10 +720,10 @@ func keyLabel() (string, error) {
|
|||||||
|
|
||||||
// get returns the Context as a string
|
// get returns the Context as a string
|
||||||
func (c Context) get() string {
|
func (c Context) get() string {
|
||||||
if level := c["level"]; level != "" {
|
if c["level"] != "" {
|
||||||
return c["user"] + ":" + c["role"] + ":" + c["type"] + ":" + level
|
return fmt.Sprintf("%s:%s:%s:%s", c["user"], c["role"], c["type"], c["level"])
|
||||||
}
|
}
|
||||||
return c["user"] + ":" + c["role"] + ":" + c["type"]
|
return fmt.Sprintf("%s:%s:%s", c["user"], c["role"], c["type"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// newContext creates a new Context struct from the specified label
|
// newContext creates a new Context struct from the specified label
|
||||||
@ -836,7 +784,7 @@ func enforceMode() int {
|
|||||||
// setEnforceMode sets the current SELinux mode Enforcing, Permissive.
|
// setEnforceMode sets the current SELinux mode Enforcing, Permissive.
|
||||||
// Disabled is not valid, since this needs to be set at boot time.
|
// Disabled is not valid, since this needs to be set at boot time.
|
||||||
func setEnforceMode(mode int) error {
|
func setEnforceMode(mode int) error {
|
||||||
return ioutil.WriteFile(selinuxEnforcePath(), []byte(strconv.Itoa(mode)), 0o644)
|
return ioutil.WriteFile(selinuxEnforcePath(), []byte(strconv.Itoa(mode)), 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultEnforceMode returns the systems default SELinux mode Enforcing,
|
// defaultEnforceMode returns the systems default SELinux mode Enforcing,
|
||||||
@ -940,21 +888,24 @@ func openContextFile() (*os.File, error) {
|
|||||||
if f, err := os.Open(contextFile); err == nil {
|
if f, err := os.Open(contextFile); err == nil {
|
||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
return os.Open(filepath.Join(policyRoot(), "/contexts/lxc_contexts"))
|
lxcPath := filepath.Join(policyRoot, "/contexts/lxc_contexts")
|
||||||
|
return os.Open(lxcPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadLabels() {
|
var labels, privContainerMountLabel = loadLabels()
|
||||||
labels = make(map[string]string)
|
|
||||||
|
func loadLabels() (map[string]string, string) {
|
||||||
|
labels := make(map[string]string)
|
||||||
in, err := openContextFile()
|
in, err := openContextFile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return labels, ""
|
||||||
}
|
}
|
||||||
defer in.Close()
|
defer in.Close()
|
||||||
|
|
||||||
scanner := bufio.NewScanner(in)
|
scanner := bufio.NewScanner(in)
|
||||||
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
line := bytes.TrimSpace(scanner.Bytes())
|
line := strings.TrimSpace(scanner.Text())
|
||||||
if len(line) == 0 {
|
if len(line) == 0 {
|
||||||
// Skip blank lines
|
// Skip blank lines
|
||||||
continue
|
continue
|
||||||
@ -963,47 +914,38 @@ func loadLabels() {
|
|||||||
// Skip comments
|
// Skip comments
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fields := bytes.SplitN(line, []byte{'='}, 2)
|
if groups := assignRegex.FindStringSubmatch(line); groups != nil {
|
||||||
if len(fields) != 2 {
|
key, val := strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2])
|
||||||
continue
|
labels[key] = strings.Trim(val, "\"")
|
||||||
}
|
}
|
||||||
key, val := bytes.TrimSpace(fields[0]), bytes.TrimSpace(fields[1])
|
|
||||||
labels[string(key)] = string(bytes.Trim(val, `"`))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
con, _ := NewContext(labels["file"])
|
con, _ := NewContext(labels["file"])
|
||||||
con["level"] = fmt.Sprintf("s0:c%d,c%d", maxCategory-2, maxCategory-1)
|
con["level"] = fmt.Sprintf("s0:c%d,c%d", maxCategory-2, maxCategory-1)
|
||||||
privContainerMountLabel = con.get()
|
reserveLabel(con.get())
|
||||||
reserveLabel(privContainerMountLabel)
|
return labels, con.get()
|
||||||
}
|
|
||||||
|
|
||||||
func label(key string) string {
|
|
||||||
loadLabelsOnce.Do(func() {
|
|
||||||
loadLabels()
|
|
||||||
})
|
|
||||||
return labels[key]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// kvmContainerLabels returns the default processLabel and mountLabel to be used
|
// kvmContainerLabels returns the default processLabel and mountLabel to be used
|
||||||
// for kvm containers by the calling process.
|
// for kvm containers by the calling process.
|
||||||
func kvmContainerLabels() (string, string) {
|
func kvmContainerLabels() (string, string) {
|
||||||
processLabel := label("kvm_process")
|
processLabel := labels["kvm_process"]
|
||||||
if processLabel == "" {
|
if processLabel == "" {
|
||||||
processLabel = label("process")
|
processLabel = labels["process"]
|
||||||
}
|
}
|
||||||
|
|
||||||
return addMcs(processLabel, label("file"))
|
return addMcs(processLabel, labels["file"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// initContainerLabels returns the default processLabel and file labels to be
|
// initContainerLabels returns the default processLabel and file labels to be
|
||||||
// used for containers running an init system like systemd by the calling process.
|
// used for containers running an init system like systemd by the calling process.
|
||||||
func initContainerLabels() (string, string) {
|
func initContainerLabels() (string, string) {
|
||||||
processLabel := label("init_process")
|
processLabel := labels["init_process"]
|
||||||
if processLabel == "" {
|
if processLabel == "" {
|
||||||
processLabel = label("process")
|
processLabel = labels["process"]
|
||||||
}
|
}
|
||||||
|
|
||||||
return addMcs(processLabel, label("file"))
|
return addMcs(processLabel, labels["file"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// containerLabels returns an allocated processLabel and fileLabel to be used for
|
// containerLabels returns an allocated processLabel and fileLabel to be used for
|
||||||
@ -1013,9 +955,9 @@ func containerLabels() (processLabel string, fileLabel string) {
|
|||||||
return "", ""
|
return "", ""
|
||||||
}
|
}
|
||||||
|
|
||||||
processLabel = label("process")
|
processLabel = labels["process"]
|
||||||
fileLabel = label("file")
|
fileLabel = labels["file"]
|
||||||
readOnlyFileLabel = label("ro_file")
|
readOnlyFileLabel = labels["ro_file"]
|
||||||
|
|
||||||
if processLabel == "" || fileLabel == "" {
|
if processLabel == "" || fileLabel == "" {
|
||||||
return "", fileLabel
|
return "", fileLabel
|
||||||
@ -1043,7 +985,7 @@ func addMcs(processLabel, fileLabel string) (string, string) {
|
|||||||
|
|
||||||
// securityCheckContext validates that the SELinux label is understood by the kernel
|
// securityCheckContext validates that the SELinux label is understood by the kernel
|
||||||
func securityCheckContext(val string) error {
|
func securityCheckContext(val string) error {
|
||||||
return ioutil.WriteFile(path.Join(getSelinuxMountPoint(), "context"), []byte(val), 0o644)
|
return ioutil.WriteFile(path.Join(getSelinuxMountPoint(), "context"), []byte(val), 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
// copyLevel returns a label with the MLS/MCS level from src label replaced on
|
// copyLevel returns a label with the MLS/MCS level from src label replaced on
|
||||||
@ -1081,7 +1023,7 @@ func badPrefix(fpath string) error {
|
|||||||
badPrefixes := []string{"/usr"}
|
badPrefixes := []string{"/usr"}
|
||||||
for _, prefix := range badPrefixes {
|
for _, prefix := range badPrefixes {
|
||||||
if strings.HasPrefix(fpath, prefix) {
|
if strings.HasPrefix(fpath, prefix) {
|
||||||
return fmt.Errorf("relabeling content in %s is not allowed", prefix)
|
return errors.Errorf("relabeling content in %s is not allowed", prefix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -1102,10 +1044,17 @@ func chcon(fpath string, label string, recurse bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !recurse {
|
if !recurse {
|
||||||
return setFileLabel(fpath, label)
|
return SetFileLabel(fpath, label)
|
||||||
}
|
}
|
||||||
|
|
||||||
return rchcon(fpath, label)
|
return pwalk.Walk(fpath, func(p string, info os.FileInfo, err error) error {
|
||||||
|
e := SetFileLabel(p, label)
|
||||||
|
// Walk a file tree can race with removal, so ignore ENOENT
|
||||||
|
if os.IsNotExist(errors.Cause(e)) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return e
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// dupSecOpt takes an SELinux process label and returns security options that
|
// dupSecOpt takes an SELinux process label and returns security options that
|
||||||
@ -1123,8 +1072,7 @@ func dupSecOpt(src string) ([]string, error) {
|
|||||||
con["type"] == "" {
|
con["type"] == "" {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
dup := []string{
|
dup := []string{"user:" + con["user"],
|
||||||
"user:" + con["user"],
|
|
||||||
"role:" + con["role"],
|
"role:" + con["role"],
|
||||||
"type:" + con["type"],
|
"type:" + con["type"],
|
||||||
}
|
}
|
||||||
@ -1192,8 +1140,9 @@ func findUserInContext(context Context, r io.Reader, verifier func(string) error
|
|||||||
return outConn, nil
|
return outConn, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
if err := scanner.Err(); err != nil {
|
||||||
return "", fmt.Errorf("failed to scan for context: %w", err)
|
return "", errors.Wrap(err, "failed to scan for context")
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", nil
|
return "", nil
|
||||||
@ -1206,7 +1155,7 @@ func getDefaultContextFromReaders(c *defaultSECtx) (string, error) {
|
|||||||
|
|
||||||
context, err := newContext(c.scon)
|
context, err := newContext(c.scon)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to create label for %s: %w", c.scon, err)
|
return "", errors.Wrapf(err, "failed to create label for %s", c.scon)
|
||||||
}
|
}
|
||||||
|
|
||||||
// set so the verifier validates the matched context with the provided user and level.
|
// set so the verifier validates the matched context with the provided user and level.
|
||||||
@ -1231,18 +1180,19 @@ func getDefaultContextFromReaders(c *defaultSECtx) (string, error) {
|
|||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", fmt.Errorf("context %q not found: %w", c.scon, ErrContextMissing)
|
return "", errors.Wrapf(ErrContextMissing, "context not found: %q", c.scon)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDefaultContextWithLevel(user, level, scon string) (string, error) {
|
func getDefaultContextWithLevel(user, level, scon string) (string, error) {
|
||||||
userPath := filepath.Join(policyRoot(), selinuxUsersDir, user)
|
userPath := filepath.Join(policyRoot, selinuxUsersDir, user)
|
||||||
|
defaultPath := filepath.Join(policyRoot, defaultContexts)
|
||||||
|
|
||||||
fu, err := os.Open(userPath)
|
fu, err := os.Open(userPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer fu.Close()
|
defer fu.Close()
|
||||||
|
|
||||||
defaultPath := filepath.Join(policyRoot(), defaultContexts)
|
|
||||||
fd, err := os.Open(defaultPath)
|
fd, err := os.Open(defaultPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|||||||
14
vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
generated
vendored
14
vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
generated
vendored
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
package selinux
|
package selinux
|
||||||
|
|
||||||
|
const privContainerMountLabel = ""
|
||||||
|
|
||||||
func setDisabled() {
|
func setDisabled() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,18 +19,10 @@ func setFileLabel(fpath string, label string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func lSetFileLabel(fpath string, label string) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func fileLabel(fpath string) (string, error) {
|
func fileLabel(fpath string) (string, error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func lFileLabel(fpath string) (string, error) {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func setFSCreateLabel(label string) error {
|
func setFSCreateLabel(label string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -158,7 +152,3 @@ func disableSecOpt() []string {
|
|||||||
func getDefaultContextWithLevel(user, level, scon string) (string, error) {
|
func getDefaultContextWithLevel(user, level, scon string) (string, error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func label(_ string) string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|||||||
37
vendor/github.com/opencontainers/selinux/go-selinux/xattrs_linux.go
generated
vendored
37
vendor/github.com/opencontainers/selinux/go-selinux/xattrs_linux.go
generated
vendored
@ -10,7 +10,7 @@ func lgetxattr(path, attr string) ([]byte, error) {
|
|||||||
// Start with a 128 length byte array
|
// Start with a 128 length byte array
|
||||||
dest := make([]byte, 128)
|
dest := make([]byte, 128)
|
||||||
sz, errno := doLgetxattr(path, attr, dest)
|
sz, errno := doLgetxattr(path, attr, dest)
|
||||||
for errno == unix.ERANGE { //nolint:errorlint // unix errors are bare
|
for errno == unix.ERANGE {
|
||||||
// Buffer too small, use zero-sized buffer to get the actual size
|
// Buffer too small, use zero-sized buffer to get the actual size
|
||||||
sz, errno = doLgetxattr(path, attr, []byte{})
|
sz, errno = doLgetxattr(path, attr, []byte{})
|
||||||
if errno != nil {
|
if errno != nil {
|
||||||
@ -31,40 +31,7 @@ func lgetxattr(path, attr string) ([]byte, error) {
|
|||||||
func doLgetxattr(path, attr string, dest []byte) (int, error) {
|
func doLgetxattr(path, attr string, dest []byte) (int, error) {
|
||||||
for {
|
for {
|
||||||
sz, err := unix.Lgetxattr(path, attr, dest)
|
sz, err := unix.Lgetxattr(path, attr, dest)
|
||||||
if err != unix.EINTR { //nolint:errorlint // unix errors are bare
|
if err != unix.EINTR {
|
||||||
return sz, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getxattr returns a []byte slice containing the value of
|
|
||||||
// an extended attribute attr set for path.
|
|
||||||
func getxattr(path, attr string) ([]byte, error) {
|
|
||||||
// Start with a 128 length byte array
|
|
||||||
dest := make([]byte, 128)
|
|
||||||
sz, errno := dogetxattr(path, attr, dest)
|
|
||||||
for errno == unix.ERANGE { //nolint:errorlint // unix errors are bare
|
|
||||||
// Buffer too small, use zero-sized buffer to get the actual size
|
|
||||||
sz, errno = dogetxattr(path, attr, []byte{})
|
|
||||||
if errno != nil {
|
|
||||||
return nil, errno
|
|
||||||
}
|
|
||||||
|
|
||||||
dest = make([]byte, sz)
|
|
||||||
sz, errno = dogetxattr(path, attr, dest)
|
|
||||||
}
|
|
||||||
if errno != nil {
|
|
||||||
return nil, errno
|
|
||||||
}
|
|
||||||
|
|
||||||
return dest[:sz], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// dogetxattr is a wrapper that retries on EINTR
|
|
||||||
func dogetxattr(path, attr string, dest []byte) (int, error) {
|
|
||||||
for {
|
|
||||||
sz, err := unix.Getxattr(path, attr, dest)
|
|
||||||
if err != unix.EINTR { //nolint:errorlint // unix errors are bare
|
|
||||||
return sz, err
|
return sz, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
vendor/github.com/opencontainers/selinux/pkg/pwalk/README.md
generated
vendored
6
vendor/github.com/opencontainers/selinux/pkg/pwalk/README.md
generated
vendored
@ -8,12 +8,6 @@ By default, it utilizes 2\*runtime.NumCPU() goroutines for callbacks.
|
|||||||
This can be changed by using WalkN function which has the additional
|
This can be changed by using WalkN function which has the additional
|
||||||
parameter, specifying the number of goroutines (concurrency).
|
parameter, specifying the number of goroutines (concurrency).
|
||||||
|
|
||||||
### pwalk vs pwalkdir
|
|
||||||
|
|
||||||
This package is deprecated in favor of
|
|
||||||
[pwalkdir](https://pkg.go.dev/github.com/opencontainers/selinux/pkg/pwalkdir),
|
|
||||||
which is faster, but requires at least Go 1.16.
|
|
||||||
|
|
||||||
### Caveats
|
### Caveats
|
||||||
|
|
||||||
Please note the following limitations of this code:
|
Please note the following limitations of this code:
|
||||||
|
|||||||
21
vendor/github.com/opencontainers/selinux/pkg/pwalk/pwalk.go
generated
vendored
21
vendor/github.com/opencontainers/selinux/pkg/pwalk/pwalk.go
generated
vendored
@ -1,11 +1,12 @@
|
|||||||
package pwalk
|
package pwalk
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type WalkFunc = filepath.WalkFunc
|
type WalkFunc = filepath.WalkFunc
|
||||||
@ -19,7 +20,7 @@ type WalkFunc = filepath.WalkFunc
|
|||||||
//
|
//
|
||||||
// Note that this implementation only supports primitive error handling:
|
// Note that this implementation only supports primitive error handling:
|
||||||
//
|
//
|
||||||
// - no errors are ever passed to walkFn;
|
// - no errors are ever passed to WalkFn;
|
||||||
//
|
//
|
||||||
// - once a walkFn returns any error, all further processing stops
|
// - once a walkFn returns any error, all further processing stops
|
||||||
// and the error is returned to the caller of Walk;
|
// and the error is returned to the caller of Walk;
|
||||||
@ -41,7 +42,7 @@ func Walk(root string, walkFn WalkFunc) error {
|
|||||||
func WalkN(root string, walkFn WalkFunc, num int) error {
|
func WalkN(root string, walkFn WalkFunc, num int) error {
|
||||||
// make sure limit is sensible
|
// make sure limit is sensible
|
||||||
if num < 1 {
|
if num < 1 {
|
||||||
return fmt.Errorf("walk(%q): num must be > 0", root)
|
return errors.Errorf("walk(%q): num must be > 0", root)
|
||||||
}
|
}
|
||||||
|
|
||||||
files := make(chan *walkArgs, 2*num)
|
files := make(chan *walkArgs, 2*num)
|
||||||
@ -51,9 +52,6 @@ func WalkN(root string, walkFn WalkFunc, num int) error {
|
|||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
rootLen = len(root)
|
|
||||||
rootEntry *walkArgs
|
|
||||||
)
|
)
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
@ -62,11 +60,6 @@ func WalkN(root string, walkFn WalkFunc, num int) error {
|
|||||||
close(files)
|
close(files)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(p) == rootLen {
|
|
||||||
// Root entry is processed separately below.
|
|
||||||
rootEntry = &walkArgs{path: p, info: &info}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// add a file to the queue unless a callback sent an error
|
// add a file to the queue unless a callback sent an error
|
||||||
select {
|
select {
|
||||||
case e := <-errCh:
|
case e := <-errCh:
|
||||||
@ -100,14 +93,10 @@ func WalkN(root string, walkFn WalkFunc, num int) error {
|
|||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
err = walkFn(rootEntry.path, *rootEntry.info, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// walkArgs holds the arguments that were passed to the Walk or WalkN
|
// walkArgs holds the arguments that were passed to the Walk or WalkLimit
|
||||||
// functions.
|
// functions.
|
||||||
type walkArgs struct {
|
type walkArgs struct {
|
||||||
path string
|
path string
|
||||||
|
|||||||
54
vendor/github.com/opencontainers/selinux/pkg/pwalkdir/README.md
generated
vendored
54
vendor/github.com/opencontainers/selinux/pkg/pwalkdir/README.md
generated
vendored
@ -1,54 +0,0 @@
|
|||||||
## pwalkdir: parallel implementation of filepath.WalkDir
|
|
||||||
|
|
||||||
This is a wrapper for [filepath.WalkDir](https://pkg.go.dev/path/filepath#WalkDir)
|
|
||||||
which may speed it up by calling multiple callback functions (WalkDirFunc)
|
|
||||||
in parallel, utilizing goroutines.
|
|
||||||
|
|
||||||
By default, it utilizes 2\*runtime.NumCPU() goroutines for callbacks.
|
|
||||||
This can be changed by using WalkN function which has the additional
|
|
||||||
parameter, specifying the number of goroutines (concurrency).
|
|
||||||
|
|
||||||
### pwalk vs pwalkdir
|
|
||||||
|
|
||||||
This package is very similar to
|
|
||||||
[pwalk](https://pkg.go.dev/github.com/opencontainers/selinux/pkg/pwalkdir),
|
|
||||||
but utilizes `filepath.WalkDir` (added to Go 1.16), which does not call stat(2)
|
|
||||||
on every entry and is therefore faster (up to 3x, depending on usage scenario).
|
|
||||||
|
|
||||||
Users who are OK with requiring Go 1.16+ should switch to this
|
|
||||||
implementation.
|
|
||||||
|
|
||||||
### Caveats
|
|
||||||
|
|
||||||
Please note the following limitations of this code:
|
|
||||||
|
|
||||||
* Unlike filepath.WalkDir, the order of calls is non-deterministic;
|
|
||||||
|
|
||||||
* Only primitive error handling is supported:
|
|
||||||
|
|
||||||
* fs.SkipDir is not supported;
|
|
||||||
|
|
||||||
* no errors are ever passed to WalkDirFunc;
|
|
||||||
|
|
||||||
* once any error is returned from any walkDirFunc instance, no more calls
|
|
||||||
to WalkDirFunc are made, and the error is returned to the caller of WalkDir;
|
|
||||||
|
|
||||||
* if more than one WalkDirFunc instance will return an error, only one
|
|
||||||
of such errors will be propagated to and returned by WalkDir, others
|
|
||||||
will be silently discarded.
|
|
||||||
|
|
||||||
### Documentation
|
|
||||||
|
|
||||||
For the official documentation, see
|
|
||||||
https://pkg.go.dev/github.com/opencontainers/selinux/pkg/pwalkdir
|
|
||||||
|
|
||||||
### Benchmarks
|
|
||||||
|
|
||||||
For a WalkDirFunc that consists solely of the return statement, this
|
|
||||||
implementation is about 15% slower than the standard library's
|
|
||||||
filepath.WalkDir.
|
|
||||||
|
|
||||||
Otherwise (if a WalkDirFunc is actually doing something) this is usually
|
|
||||||
faster, except when the WalkDirN(..., 1) is used. Run `go test -bench .`
|
|
||||||
to see how different operations can benefit from it, as well as how the
|
|
||||||
level of paralellism affects the speed.
|
|
||||||
116
vendor/github.com/opencontainers/selinux/pkg/pwalkdir/pwalkdir.go
generated
vendored
116
vendor/github.com/opencontainers/selinux/pkg/pwalkdir/pwalkdir.go
generated
vendored
@ -1,116 +0,0 @@
|
|||||||
//go:build go1.16
|
|
||||||
// +build go1.16
|
|
||||||
|
|
||||||
package pwalkdir
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io/fs"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Walk is a wrapper for filepath.WalkDir which can call multiple walkFn
|
|
||||||
// in parallel, allowing to handle each item concurrently. A maximum of
|
|
||||||
// twice the runtime.NumCPU() walkFn will be called at any one time.
|
|
||||||
// If you want to change the maximum, use WalkN instead.
|
|
||||||
//
|
|
||||||
// The order of calls is non-deterministic.
|
|
||||||
//
|
|
||||||
// Note that this implementation only supports primitive error handling:
|
|
||||||
//
|
|
||||||
// - no errors are ever passed to walkFn;
|
|
||||||
//
|
|
||||||
// - once a walkFn returns any error, all further processing stops
|
|
||||||
// and the error is returned to the caller of Walk;
|
|
||||||
//
|
|
||||||
// - filepath.SkipDir is not supported;
|
|
||||||
//
|
|
||||||
// - if more than one walkFn instance will return an error, only one
|
|
||||||
// of such errors will be propagated and returned by Walk, others
|
|
||||||
// will be silently discarded.
|
|
||||||
func Walk(root string, walkFn fs.WalkDirFunc) error {
|
|
||||||
return WalkN(root, walkFn, runtime.NumCPU()*2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WalkN is a wrapper for filepath.WalkDir which can call multiple walkFn
|
|
||||||
// in parallel, allowing to handle each item concurrently. A maximum of
|
|
||||||
// num walkFn will be called at any one time.
|
|
||||||
//
|
|
||||||
// Please see Walk documentation for caveats of using this function.
|
|
||||||
func WalkN(root string, walkFn fs.WalkDirFunc, num int) error {
|
|
||||||
// make sure limit is sensible
|
|
||||||
if num < 1 {
|
|
||||||
return fmt.Errorf("walk(%q): num must be > 0", root)
|
|
||||||
}
|
|
||||||
|
|
||||||
files := make(chan *walkArgs, 2*num)
|
|
||||||
errCh := make(chan error, 1) // Get the first error, ignore others.
|
|
||||||
|
|
||||||
// Start walking a tree asap.
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
wg sync.WaitGroup
|
|
||||||
|
|
||||||
rootLen = len(root)
|
|
||||||
rootEntry *walkArgs
|
|
||||||
)
|
|
||||||
wg.Add(1)
|
|
||||||
go func() {
|
|
||||||
err = filepath.WalkDir(root, func(p string, entry fs.DirEntry, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
close(files)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(p) == rootLen {
|
|
||||||
// Root entry is processed separately below.
|
|
||||||
rootEntry = &walkArgs{path: p, entry: entry}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// Add a file to the queue unless a callback sent an error.
|
|
||||||
select {
|
|
||||||
case e := <-errCh:
|
|
||||||
close(files)
|
|
||||||
return e
|
|
||||||
default:
|
|
||||||
files <- &walkArgs{path: p, entry: entry}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if err == nil {
|
|
||||||
close(files)
|
|
||||||
}
|
|
||||||
wg.Done()
|
|
||||||
}()
|
|
||||||
|
|
||||||
wg.Add(num)
|
|
||||||
for i := 0; i < num; i++ {
|
|
||||||
go func() {
|
|
||||||
for file := range files {
|
|
||||||
if e := walkFn(file.path, file.entry, nil); e != nil {
|
|
||||||
select {
|
|
||||||
case errCh <- e: // sent ok
|
|
||||||
default: // buffer full
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wg.Done()
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
err = walkFn(rootEntry.path, rootEntry.entry, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// walkArgs holds the arguments that were passed to the Walk or WalkN
|
|
||||||
// functions.
|
|
||||||
type walkArgs struct {
|
|
||||||
path string
|
|
||||||
entry fs.DirEntry
|
|
||||||
}
|
|
||||||
28
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go
generated
vendored
28
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go
generated
vendored
@ -49,10 +49,7 @@ func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripp
|
|||||||
// http.RoundTripper to observe the request result with the provided CounterVec.
|
// http.RoundTripper to observe the request result with the provided CounterVec.
|
||||||
// The CounterVec must have zero, one, or two non-const non-curried labels. For
|
// The CounterVec must have zero, one, or two non-const non-curried labels. For
|
||||||
// those, the only allowed label names are "code" and "method". The function
|
// those, the only allowed label names are "code" and "method". The function
|
||||||
// panics otherwise. For the "method" label a predefined default label value set
|
// panics otherwise. Partitioning of the CounterVec happens by HTTP status code
|
||||||
// is used to filter given values. Values besides predefined values will count
|
|
||||||
// as `unknown` method.`WithExtraMethods` can be used to add more
|
|
||||||
// methods to the set. Partitioning of the CounterVec happens by HTTP status code
|
|
||||||
// and/or HTTP method if the respective instance label names are present in the
|
// and/or HTTP method if the respective instance label names are present in the
|
||||||
// CounterVec. For unpartitioned counting, use a CounterVec with zero labels.
|
// CounterVec. For unpartitioned counting, use a CounterVec with zero labels.
|
||||||
//
|
//
|
||||||
@ -60,18 +57,13 @@ func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripp
|
|||||||
// is not incremented.
|
// is not incremented.
|
||||||
//
|
//
|
||||||
// See the example for ExampleInstrumentRoundTripperDuration for example usage.
|
// See the example for ExampleInstrumentRoundTripperDuration for example usage.
|
||||||
func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper, opts ...Option) RoundTripperFunc {
|
func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper) RoundTripperFunc {
|
||||||
rtOpts := &option{}
|
|
||||||
for _, o := range opts {
|
|
||||||
o(rtOpts)
|
|
||||||
}
|
|
||||||
|
|
||||||
code, method := checkLabels(counter)
|
code, method := checkLabels(counter)
|
||||||
|
|
||||||
return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
|
return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
|
||||||
resp, err := next.RoundTrip(r)
|
resp, err := next.RoundTrip(r)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
counter.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)).Inc()
|
counter.With(labels(code, method, r.Method, resp.StatusCode)).Inc()
|
||||||
}
|
}
|
||||||
return resp, err
|
return resp, err
|
||||||
})
|
})
|
||||||
@ -81,10 +73,7 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou
|
|||||||
// http.RoundTripper to observe the request duration with the provided
|
// http.RoundTripper to observe the request duration with the provided
|
||||||
// ObserverVec. The ObserverVec must have zero, one, or two non-const
|
// ObserverVec. The ObserverVec must have zero, one, or two non-const
|
||||||
// non-curried labels. For those, the only allowed label names are "code" and
|
// non-curried labels. For those, the only allowed label names are "code" and
|
||||||
// "method". The function panics otherwise. For the "method" label a predefined
|
// "method". The function panics otherwise. The Observe method of the Observer
|
||||||
// default label value set is used to filter given values. Values besides
|
|
||||||
// predefined values will count as `unknown` method. `WithExtraMethods`
|
|
||||||
// can be used to add more methods to the set. The Observe method of the Observer
|
|
||||||
// in the ObserverVec is called with the request duration in
|
// in the ObserverVec is called with the request duration in
|
||||||
// seconds. Partitioning happens by HTTP status code and/or HTTP method if the
|
// seconds. Partitioning happens by HTTP status code and/or HTTP method if the
|
||||||
// respective instance label names are present in the ObserverVec. For
|
// respective instance label names are present in the ObserverVec. For
|
||||||
@ -96,19 +85,14 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou
|
|||||||
//
|
//
|
||||||
// Note that this method is only guaranteed to never observe negative durations
|
// Note that this method is only guaranteed to never observe negative durations
|
||||||
// if used with Go1.9+.
|
// if used with Go1.9+.
|
||||||
func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper, opts ...Option) RoundTripperFunc {
|
func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper) RoundTripperFunc {
|
||||||
rtOpts := &option{}
|
|
||||||
for _, o := range opts {
|
|
||||||
o(rtOpts)
|
|
||||||
}
|
|
||||||
|
|
||||||
code, method := checkLabels(obs)
|
code, method := checkLabels(obs)
|
||||||
|
|
||||||
return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
|
return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
resp, err := next.RoundTrip(r)
|
resp, err := next.RoundTrip(r)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
obs.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)).Observe(time.Since(start).Seconds())
|
obs.With(labels(code, method, r.Method, resp.StatusCode)).Observe(time.Since(start).Seconds())
|
||||||
}
|
}
|
||||||
return resp, err
|
return resp, err
|
||||||
})
|
})
|
||||||
|
|||||||
107
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go
generated
vendored
107
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go
generated
vendored
@ -45,10 +45,7 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl
|
|||||||
// http.Handler to observe the request duration with the provided ObserverVec.
|
// http.Handler to observe the request duration with the provided ObserverVec.
|
||||||
// The ObserverVec must have valid metric and label names and must have zero,
|
// The ObserverVec must have valid metric and label names and must have zero,
|
||||||
// one, or two non-const non-curried labels. For those, the only allowed label
|
// one, or two non-const non-curried labels. For those, the only allowed label
|
||||||
// names are "code" and "method". The function panics otherwise. For the "method"
|
// names are "code" and "method". The function panics otherwise. The Observe
|
||||||
// label a predefined default label value set is used to filter given values.
|
|
||||||
// Values besides predefined values will count as `unknown` method.
|
|
||||||
//`WithExtraMethods` can be used to add more methods to the set. The Observe
|
|
||||||
// method of the Observer in the ObserverVec is called with the request duration
|
// method of the Observer in the ObserverVec is called with the request duration
|
||||||
// in seconds. Partitioning happens by HTTP status code and/or HTTP method if
|
// in seconds. Partitioning happens by HTTP status code and/or HTTP method if
|
||||||
// the respective instance label names are present in the ObserverVec. For
|
// the respective instance label names are present in the ObserverVec. For
|
||||||
@ -61,12 +58,7 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl
|
|||||||
//
|
//
|
||||||
// Note that this method is only guaranteed to never observe negative durations
|
// Note that this method is only guaranteed to never observe negative durations
|
||||||
// if used with Go1.9+.
|
// if used with Go1.9+.
|
||||||
func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc {
|
func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc {
|
||||||
mwOpts := &option{}
|
|
||||||
for _, o := range opts {
|
|
||||||
o(mwOpts)
|
|
||||||
}
|
|
||||||
|
|
||||||
code, method := checkLabels(obs)
|
code, method := checkLabels(obs)
|
||||||
|
|
||||||
if code {
|
if code {
|
||||||
@ -75,14 +67,14 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, op
|
|||||||
d := newDelegator(w, nil)
|
d := newDelegator(w, nil)
|
||||||
next.ServeHTTP(d, r)
|
next.ServeHTTP(d, r)
|
||||||
|
|
||||||
obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(time.Since(now).Seconds())
|
obs.With(labels(code, method, r.Method, d.Status())).Observe(time.Since(now).Seconds())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
obs.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Observe(time.Since(now).Seconds())
|
obs.With(labels(code, method, r.Method, 0)).Observe(time.Since(now).Seconds())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,10 +82,7 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, op
|
|||||||
// to observe the request result with the provided CounterVec. The CounterVec
|
// to observe the request result with the provided CounterVec. The CounterVec
|
||||||
// must have valid metric and label names and must have zero, one, or two
|
// must have valid metric and label names and must have zero, one, or two
|
||||||
// non-const non-curried labels. For those, the only allowed label names are
|
// non-const non-curried labels. For those, the only allowed label names are
|
||||||
// "code" and "method". The function panics otherwise. For the "method"
|
// "code" and "method". The function panics otherwise. Partitioning of the
|
||||||
// label a predefined default label value set is used to filter given values.
|
|
||||||
// Values besides predefined values will count as `unknown` method.
|
|
||||||
// `WithExtraMethods` can be used to add more methods to the set. Partitioning of the
|
|
||||||
// CounterVec happens by HTTP status code and/or HTTP method if the respective
|
// CounterVec happens by HTTP status code and/or HTTP method if the respective
|
||||||
// instance label names are present in the CounterVec. For unpartitioned
|
// instance label names are present in the CounterVec. For unpartitioned
|
||||||
// counting, use a CounterVec with zero labels.
|
// counting, use a CounterVec with zero labels.
|
||||||
@ -103,25 +92,20 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, op
|
|||||||
// If the wrapped Handler panics, the Counter is not incremented.
|
// If the wrapped Handler panics, the Counter is not incremented.
|
||||||
//
|
//
|
||||||
// See the example for InstrumentHandlerDuration for example usage.
|
// See the example for InstrumentHandlerDuration for example usage.
|
||||||
func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler, opts ...Option) http.HandlerFunc {
|
func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) http.HandlerFunc {
|
||||||
mwOpts := &option{}
|
|
||||||
for _, o := range opts {
|
|
||||||
o(mwOpts)
|
|
||||||
}
|
|
||||||
|
|
||||||
code, method := checkLabels(counter)
|
code, method := checkLabels(counter)
|
||||||
|
|
||||||
if code {
|
if code {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
d := newDelegator(w, nil)
|
d := newDelegator(w, nil)
|
||||||
next.ServeHTTP(d, r)
|
next.ServeHTTP(d, r)
|
||||||
counter.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Inc()
|
counter.With(labels(code, method, r.Method, d.Status())).Inc()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
counter.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Inc()
|
counter.With(labels(code, method, r.Method, 0)).Inc()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,10 +114,7 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler,
|
|||||||
// until the response headers are written. The ObserverVec must have valid
|
// until the response headers are written. The ObserverVec must have valid
|
||||||
// metric and label names and must have zero, one, or two non-const non-curried
|
// metric and label names and must have zero, one, or two non-const non-curried
|
||||||
// labels. For those, the only allowed label names are "code" and "method". The
|
// labels. For those, the only allowed label names are "code" and "method". The
|
||||||
// function panics otherwise. For the "method" label a predefined default label
|
// function panics otherwise. The Observe method of the Observer in the
|
||||||
// value set is used to filter given values. Values besides predefined values
|
|
||||||
// will count as `unknown` method.`WithExtraMethods` can be used to add more
|
|
||||||
// methods to the set. The Observe method of the Observer in the
|
|
||||||
// ObserverVec is called with the request duration in seconds. Partitioning
|
// ObserverVec is called with the request duration in seconds. Partitioning
|
||||||
// happens by HTTP status code and/or HTTP method if the respective instance
|
// happens by HTTP status code and/or HTTP method if the respective instance
|
||||||
// label names are present in the ObserverVec. For unpartitioned observations,
|
// label names are present in the ObserverVec. For unpartitioned observations,
|
||||||
@ -147,18 +128,13 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler,
|
|||||||
// if used with Go1.9+.
|
// if used with Go1.9+.
|
||||||
//
|
//
|
||||||
// See the example for InstrumentHandlerDuration for example usage.
|
// See the example for InstrumentHandlerDuration for example usage.
|
||||||
func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc {
|
func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc {
|
||||||
mwOpts := &option{}
|
|
||||||
for _, o := range opts {
|
|
||||||
o(mwOpts)
|
|
||||||
}
|
|
||||||
|
|
||||||
code, method := checkLabels(obs)
|
code, method := checkLabels(obs)
|
||||||
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
d := newDelegator(w, func(status int) {
|
d := newDelegator(w, func(status int) {
|
||||||
obs.With(labels(code, method, r.Method, status, mwOpts.extraMethods...)).Observe(time.Since(now).Seconds())
|
obs.With(labels(code, method, r.Method, status)).Observe(time.Since(now).Seconds())
|
||||||
})
|
})
|
||||||
next.ServeHTTP(d, r)
|
next.ServeHTTP(d, r)
|
||||||
})
|
})
|
||||||
@ -168,11 +144,8 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha
|
|||||||
// http.Handler to observe the request size with the provided ObserverVec. The
|
// http.Handler to observe the request size with the provided ObserverVec. The
|
||||||
// ObserverVec must have valid metric and label names and must have zero, one,
|
// ObserverVec must have valid metric and label names and must have zero, one,
|
||||||
// or two non-const non-curried labels. For those, the only allowed label names
|
// or two non-const non-curried labels. For those, the only allowed label names
|
||||||
// are "code" and "method". The function panics otherwise. For the "method"
|
// are "code" and "method". The function panics otherwise. The Observe method of
|
||||||
// label a predefined default label value set is used to filter given values.
|
// the Observer in the ObserverVec is called with the request size in
|
||||||
// Values besides predefined values will count as `unknown` method.
|
|
||||||
// `WithExtraMethods` can be used to add more methods to the set. The Observe
|
|
||||||
// method of the Observer in the ObserverVec is called with the request size in
|
|
||||||
// bytes. Partitioning happens by HTTP status code and/or HTTP method if the
|
// bytes. Partitioning happens by HTTP status code and/or HTTP method if the
|
||||||
// respective instance label names are present in the ObserverVec. For
|
// respective instance label names are present in the ObserverVec. For
|
||||||
// unpartitioned observations, use an ObserverVec with zero labels. Note that
|
// unpartitioned observations, use an ObserverVec with zero labels. Note that
|
||||||
@ -183,12 +156,7 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha
|
|||||||
// If the wrapped Handler panics, no values are reported.
|
// If the wrapped Handler panics, no values are reported.
|
||||||
//
|
//
|
||||||
// See the example for InstrumentHandlerDuration for example usage.
|
// See the example for InstrumentHandlerDuration for example usage.
|
||||||
func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc {
|
func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc {
|
||||||
mwOpts := &option{}
|
|
||||||
for _, o := range opts {
|
|
||||||
o(mwOpts)
|
|
||||||
}
|
|
||||||
|
|
||||||
code, method := checkLabels(obs)
|
code, method := checkLabels(obs)
|
||||||
|
|
||||||
if code {
|
if code {
|
||||||
@ -196,14 +164,14 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler,
|
|||||||
d := newDelegator(w, nil)
|
d := newDelegator(w, nil)
|
||||||
next.ServeHTTP(d, r)
|
next.ServeHTTP(d, r)
|
||||||
size := computeApproximateRequestSize(r)
|
size := computeApproximateRequestSize(r)
|
||||||
obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(float64(size))
|
obs.With(labels(code, method, r.Method, d.Status())).Observe(float64(size))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
size := computeApproximateRequestSize(r)
|
size := computeApproximateRequestSize(r)
|
||||||
obs.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Observe(float64(size))
|
obs.With(labels(code, method, r.Method, 0)).Observe(float64(size))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,11 +179,8 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler,
|
|||||||
// http.Handler to observe the response size with the provided ObserverVec. The
|
// http.Handler to observe the response size with the provided ObserverVec. The
|
||||||
// ObserverVec must have valid metric and label names and must have zero, one,
|
// ObserverVec must have valid metric and label names and must have zero, one,
|
||||||
// or two non-const non-curried labels. For those, the only allowed label names
|
// or two non-const non-curried labels. For those, the only allowed label names
|
||||||
// are "code" and "method". The function panics otherwise. For the "method"
|
// are "code" and "method". The function panics otherwise. The Observe method of
|
||||||
// label a predefined default label value set is used to filter given values.
|
// the Observer in the ObserverVec is called with the response size in
|
||||||
// Values besides predefined values will count as `unknown` method.
|
|
||||||
// `WithExtraMethods` can be used to add more methods to the set. The Observe
|
|
||||||
// method of the Observer in the ObserverVec is called with the response size in
|
|
||||||
// bytes. Partitioning happens by HTTP status code and/or HTTP method if the
|
// bytes. Partitioning happens by HTTP status code and/or HTTP method if the
|
||||||
// respective instance label names are present in the ObserverVec. For
|
// respective instance label names are present in the ObserverVec. For
|
||||||
// unpartitioned observations, use an ObserverVec with zero labels. Note that
|
// unpartitioned observations, use an ObserverVec with zero labels. Note that
|
||||||
@ -226,18 +191,12 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler,
|
|||||||
// If the wrapped Handler panics, no values are reported.
|
// If the wrapped Handler panics, no values are reported.
|
||||||
//
|
//
|
||||||
// See the example for InstrumentHandlerDuration for example usage.
|
// See the example for InstrumentHandlerDuration for example usage.
|
||||||
func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.Handler {
|
func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler) http.Handler {
|
||||||
mwOpts := &option{}
|
|
||||||
for _, o := range opts {
|
|
||||||
o(mwOpts)
|
|
||||||
}
|
|
||||||
|
|
||||||
code, method := checkLabels(obs)
|
code, method := checkLabels(obs)
|
||||||
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
d := newDelegator(w, nil)
|
d := newDelegator(w, nil)
|
||||||
next.ServeHTTP(d, r)
|
next.ServeHTTP(d, r)
|
||||||
obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(float64(d.Written()))
|
obs.With(labels(code, method, r.Method, d.Status())).Observe(float64(d.Written()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,7 +290,7 @@ func isLabelCurried(c prometheus.Collector, label string) bool {
|
|||||||
// unnecessary allocations on each request.
|
// unnecessary allocations on each request.
|
||||||
var emptyLabels = prometheus.Labels{}
|
var emptyLabels = prometheus.Labels{}
|
||||||
|
|
||||||
func labels(code, method bool, reqMethod string, status int, extraMethods ...string) prometheus.Labels {
|
func labels(code, method bool, reqMethod string, status int) prometheus.Labels {
|
||||||
if !(code || method) {
|
if !(code || method) {
|
||||||
return emptyLabels
|
return emptyLabels
|
||||||
}
|
}
|
||||||
@ -341,7 +300,7 @@ func labels(code, method bool, reqMethod string, status int, extraMethods ...str
|
|||||||
labels["code"] = sanitizeCode(status)
|
labels["code"] = sanitizeCode(status)
|
||||||
}
|
}
|
||||||
if method {
|
if method {
|
||||||
labels["method"] = sanitizeMethod(reqMethod, extraMethods...)
|
labels["method"] = sanitizeMethod(reqMethod)
|
||||||
}
|
}
|
||||||
|
|
||||||
return labels
|
return labels
|
||||||
@ -371,12 +330,7 @@ func computeApproximateRequestSize(r *http.Request) int {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the wrapped http.Handler has a known method, it will be sanitized and returned.
|
func sanitizeMethod(m string) string {
|
||||||
// Otherwise, "unknown" will be returned. The known method list can be extended
|
|
||||||
// as needed by using extraMethods parameter.
|
|
||||||
func sanitizeMethod(m string, extraMethods ...string) string {
|
|
||||||
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods for
|
|
||||||
// the methods chosen as default.
|
|
||||||
switch m {
|
switch m {
|
||||||
case "GET", "get":
|
case "GET", "get":
|
||||||
return "get"
|
return "get"
|
||||||
@ -394,25 +348,15 @@ func sanitizeMethod(m string, extraMethods ...string) string {
|
|||||||
return "options"
|
return "options"
|
||||||
case "NOTIFY", "notify":
|
case "NOTIFY", "notify":
|
||||||
return "notify"
|
return "notify"
|
||||||
case "TRACE", "trace":
|
|
||||||
return "trace"
|
|
||||||
case "PATCH", "patch":
|
|
||||||
return "patch"
|
|
||||||
default:
|
default:
|
||||||
for _, method := range extraMethods {
|
|
||||||
if strings.EqualFold(m, method) {
|
|
||||||
return strings.ToLower(m)
|
return strings.ToLower(m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "unknown"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the wrapped http.Handler has not set a status code, i.e. the value is
|
// If the wrapped http.Handler has not set a status code, i.e. the value is
|
||||||
// currently 0, sanitizeCode will return 200, for consistency with behavior in
|
// currently 0, santizeCode will return 200, for consistency with behavior in
|
||||||
// the stdlib.
|
// the stdlib.
|
||||||
func sanitizeCode(s int) string {
|
func sanitizeCode(s int) string {
|
||||||
// See for accepted codes https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
|
||||||
switch s {
|
switch s {
|
||||||
case 100:
|
case 100:
|
||||||
return "100"
|
return "100"
|
||||||
@ -509,9 +453,6 @@ func sanitizeCode(s int) string {
|
|||||||
return "511"
|
return "511"
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if s >= 100 && s <= 599 {
|
|
||||||
return strconv.Itoa(s)
|
return strconv.Itoa(s)
|
||||||
}
|
}
|
||||||
return "unknown"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
31
vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go
generated
vendored
31
vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go
generated
vendored
@ -1,31 +0,0 @@
|
|||||||
// Copyright 2022 The Prometheus Authors
|
|
||||||
// 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 promhttp
|
|
||||||
|
|
||||||
// Option are used to configure a middleware or round tripper..
|
|
||||||
type Option func(*option)
|
|
||||||
|
|
||||||
type option struct {
|
|
||||||
extraMethods []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithExtraMethods adds additional HTTP methods to the list of allowed methods.
|
|
||||||
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods for the default list.
|
|
||||||
//
|
|
||||||
// See the example for ExampleInstrumentHandlerWithExtraMethods for example usage.
|
|
||||||
func WithExtraMethods(methods ...string) Option {
|
|
||||||
return func(o *option) {
|
|
||||||
o.extraMethods = methods
|
|
||||||
}
|
|
||||||
}
|
|
||||||
3
vendor/golang.org/x/crypto/AUTHORS
generated
vendored
Normal file
3
vendor/golang.org/x/crypto/AUTHORS
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# This source code refers to The Go Authors for copyright purposes.
|
||||||
|
# The master list of authors is in the main Go distribution,
|
||||||
|
# visible at https://tip.golang.org/AUTHORS.
|
||||||
3
vendor/golang.org/x/crypto/CONTRIBUTORS
generated
vendored
Normal file
3
vendor/golang.org/x/crypto/CONTRIBUTORS
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# This source code was written by the Go contributors.
|
||||||
|
# The master list of contributors is in the main Go distribution,
|
||||||
|
# visible at https://tip.golang.org/CONTRIBUTORS.
|
||||||
4
vendor/golang.org/x/crypto/chacha20/chacha_generic.go
generated
vendored
4
vendor/golang.org/x/crypto/chacha20/chacha_generic.go
generated
vendored
@ -12,7 +12,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"math/bits"
|
"math/bits"
|
||||||
|
|
||||||
"golang.org/x/crypto/internal/alias"
|
"golang.org/x/crypto/internal/subtle"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -189,7 +189,7 @@ func (s *Cipher) XORKeyStream(dst, src []byte) {
|
|||||||
panic("chacha20: output smaller than input")
|
panic("chacha20: output smaller than input")
|
||||||
}
|
}
|
||||||
dst = dst[:len(src)]
|
dst = dst[:len(src)]
|
||||||
if alias.InexactOverlap(dst, src) {
|
if subtle.InexactOverlap(dst, src) {
|
||||||
panic("chacha20: invalid buffer overlap")
|
panic("chacha20: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/crypto/chacha20/chacha_s390x.go
generated
vendored
1
vendor/golang.org/x/crypto/chacha20/chacha_s390x.go
generated
vendored
@ -15,7 +15,6 @@ const bufSize = 256
|
|||||||
|
|
||||||
// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only
|
// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only
|
||||||
// be called when the vector facility is available. Implementation in asm_s390x.s.
|
// be called when the vector facility is available. Implementation in asm_s390x.s.
|
||||||
//
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
|
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
|
||||||
|
|
||||||
|
|||||||
9
vendor/golang.org/x/crypto/curve25519/curve25519.go
generated
vendored
9
vendor/golang.org/x/crypto/curve25519/curve25519.go
generated
vendored
@ -9,8 +9,7 @@ package curve25519 // import "golang.org/x/crypto/curve25519"
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"errors"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/curve25519/internal/field"
|
"golang.org/x/crypto/curve25519/internal/field"
|
||||||
)
|
)
|
||||||
@ -125,10 +124,10 @@ func X25519(scalar, point []byte) ([]byte, error) {
|
|||||||
func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
|
func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
|
||||||
var in [32]byte
|
var in [32]byte
|
||||||
if l := len(scalar); l != 32 {
|
if l := len(scalar); l != 32 {
|
||||||
return nil, errors.New("bad scalar length: " + strconv.Itoa(l) + ", expected 32")
|
return nil, fmt.Errorf("bad scalar length: %d, expected %d", l, 32)
|
||||||
}
|
}
|
||||||
if l := len(point); l != 32 {
|
if l := len(point); l != 32 {
|
||||||
return nil, errors.New("bad point length: " + strconv.Itoa(l) + ", expected 32")
|
return nil, fmt.Errorf("bad point length: %d, expected %d", l, 32)
|
||||||
}
|
}
|
||||||
copy(in[:], scalar)
|
copy(in[:], scalar)
|
||||||
if &point[0] == &Basepoint[0] {
|
if &point[0] == &Basepoint[0] {
|
||||||
@ -139,7 +138,7 @@ func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
|
|||||||
copy(base[:], point)
|
copy(base[:], point)
|
||||||
ScalarMult(dst, &in, &base)
|
ScalarMult(dst, &in, &base)
|
||||||
if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 {
|
if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 {
|
||||||
return nil, errors.New("bad input point: low order point")
|
return nil, fmt.Errorf("bad input point: low order point")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dst[:], nil
|
return dst[:], nil
|
||||||
|
|||||||
3
vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go
generated
vendored
3
vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go
generated
vendored
@ -1,16 +1,13 @@
|
|||||||
// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT.
|
// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build amd64 && gc && !purego
|
|
||||||
// +build amd64,gc,!purego
|
// +build amd64,gc,!purego
|
||||||
|
|
||||||
package field
|
package field
|
||||||
|
|
||||||
// feMul sets out = a * b. It works like feMulGeneric.
|
// feMul sets out = a * b. It works like feMulGeneric.
|
||||||
//
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func feMul(out *Element, a *Element, b *Element)
|
func feMul(out *Element, a *Element, b *Element)
|
||||||
|
|
||||||
// feSquare sets out = a * a. It works like feSquareGeneric.
|
// feSquare sets out = a * a. It works like feSquareGeneric.
|
||||||
//
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func feSquare(out *Element, a *Element)
|
func feSquare(out *Element, a *Element)
|
||||||
|
|||||||
188
vendor/golang.org/x/crypto/ed25519/ed25519.go
generated
vendored
188
vendor/golang.org/x/crypto/ed25519/ed25519.go
generated
vendored
@ -1,7 +1,13 @@
|
|||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
// 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.
|
||||||
|
|
||||||
|
// In Go 1.13, the ed25519 package was promoted to the standard library as
|
||||||
|
// crypto/ed25519, and this package became a wrapper for the standard library one.
|
||||||
|
//
|
||||||
|
//go:build !go1.13
|
||||||
|
// +build !go1.13
|
||||||
|
|
||||||
// Package ed25519 implements the Ed25519 signature algorithm. See
|
// Package ed25519 implements the Ed25519 signature algorithm. See
|
||||||
// https://ed25519.cr.yp.to/.
|
// https://ed25519.cr.yp.to/.
|
||||||
//
|
//
|
||||||
@ -10,15 +16,21 @@
|
|||||||
// representation includes a public key suffix to make multiple signing
|
// representation includes a public key suffix to make multiple signing
|
||||||
// operations with the same key more efficient. This package refers to the RFC
|
// operations with the same key more efficient. This package refers to the RFC
|
||||||
// 8032 private key as the “seed”.
|
// 8032 private key as the “seed”.
|
||||||
//
|
|
||||||
// Beginning with Go 1.13, the functionality of this package was moved to the
|
|
||||||
// standard library as crypto/ed25519. This package only acts as a compatibility
|
|
||||||
// wrapper.
|
|
||||||
package ed25519
|
package ed25519
|
||||||
|
|
||||||
|
// This code is a port of the public domain, “ref10” implementation of ed25519
|
||||||
|
// from SUPERCOP.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ed25519"
|
"bytes"
|
||||||
|
"crypto"
|
||||||
|
cryptorand "crypto/rand"
|
||||||
|
"crypto/sha512"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ed25519/internal/edwards25519"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -33,21 +45,57 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// PublicKey is the type of Ed25519 public keys.
|
// PublicKey is the type of Ed25519 public keys.
|
||||||
//
|
type PublicKey []byte
|
||||||
// This type is an alias for crypto/ed25519's PublicKey type.
|
|
||||||
// See the crypto/ed25519 package for the methods on this type.
|
|
||||||
type PublicKey = ed25519.PublicKey
|
|
||||||
|
|
||||||
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
|
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
|
||||||
//
|
type PrivateKey []byte
|
||||||
// This type is an alias for crypto/ed25519's PrivateKey type.
|
|
||||||
// See the crypto/ed25519 package for the methods on this type.
|
// Public returns the PublicKey corresponding to priv.
|
||||||
type PrivateKey = ed25519.PrivateKey
|
func (priv PrivateKey) Public() crypto.PublicKey {
|
||||||
|
publicKey := make([]byte, PublicKeySize)
|
||||||
|
copy(publicKey, priv[32:])
|
||||||
|
return PublicKey(publicKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seed returns the private key seed corresponding to priv. It is provided for
|
||||||
|
// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds
|
||||||
|
// in this package.
|
||||||
|
func (priv PrivateKey) Seed() []byte {
|
||||||
|
seed := make([]byte, SeedSize)
|
||||||
|
copy(seed, priv[:32])
|
||||||
|
return seed
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign signs the given message with priv.
|
||||||
|
// Ed25519 performs two passes over messages to be signed and therefore cannot
|
||||||
|
// handle pre-hashed messages. Thus opts.HashFunc() must return zero to
|
||||||
|
// indicate the message hasn't been hashed. This can be achieved by passing
|
||||||
|
// crypto.Hash(0) as the value for opts.
|
||||||
|
func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) {
|
||||||
|
if opts.HashFunc() != crypto.Hash(0) {
|
||||||
|
return nil, errors.New("ed25519: cannot sign hashed message")
|
||||||
|
}
|
||||||
|
|
||||||
|
return Sign(priv, message), nil
|
||||||
|
}
|
||||||
|
|
||||||
// GenerateKey generates a public/private key pair using entropy from rand.
|
// GenerateKey generates a public/private key pair using entropy from rand.
|
||||||
// If rand is nil, crypto/rand.Reader will be used.
|
// If rand is nil, crypto/rand.Reader will be used.
|
||||||
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
|
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
|
||||||
return ed25519.GenerateKey(rand)
|
if rand == nil {
|
||||||
|
rand = cryptorand.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
seed := make([]byte, SeedSize)
|
||||||
|
if _, err := io.ReadFull(rand, seed); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKey := NewKeyFromSeed(seed)
|
||||||
|
publicKey := make([]byte, PublicKeySize)
|
||||||
|
copy(publicKey, privateKey[32:])
|
||||||
|
|
||||||
|
return publicKey, privateKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewKeyFromSeed calculates a private key from a seed. It will panic if
|
// NewKeyFromSeed calculates a private key from a seed. It will panic if
|
||||||
@ -55,17 +103,121 @@ func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
|
|||||||
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
|
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
|
||||||
// package.
|
// package.
|
||||||
func NewKeyFromSeed(seed []byte) PrivateKey {
|
func NewKeyFromSeed(seed []byte) PrivateKey {
|
||||||
return ed25519.NewKeyFromSeed(seed)
|
if l := len(seed); l != SeedSize {
|
||||||
|
panic("ed25519: bad seed length: " + strconv.Itoa(l))
|
||||||
|
}
|
||||||
|
|
||||||
|
digest := sha512.Sum512(seed)
|
||||||
|
digest[0] &= 248
|
||||||
|
digest[31] &= 127
|
||||||
|
digest[31] |= 64
|
||||||
|
|
||||||
|
var A edwards25519.ExtendedGroupElement
|
||||||
|
var hBytes [32]byte
|
||||||
|
copy(hBytes[:], digest[:])
|
||||||
|
edwards25519.GeScalarMultBase(&A, &hBytes)
|
||||||
|
var publicKeyBytes [32]byte
|
||||||
|
A.ToBytes(&publicKeyBytes)
|
||||||
|
|
||||||
|
privateKey := make([]byte, PrivateKeySize)
|
||||||
|
copy(privateKey, seed)
|
||||||
|
copy(privateKey[32:], publicKeyBytes[:])
|
||||||
|
|
||||||
|
return privateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sign signs the message with privateKey and returns a signature. It will
|
// Sign signs the message with privateKey and returns a signature. It will
|
||||||
// panic if len(privateKey) is not PrivateKeySize.
|
// panic if len(privateKey) is not PrivateKeySize.
|
||||||
func Sign(privateKey PrivateKey, message []byte) []byte {
|
func Sign(privateKey PrivateKey, message []byte) []byte {
|
||||||
return ed25519.Sign(privateKey, message)
|
if l := len(privateKey); l != PrivateKeySize {
|
||||||
|
panic("ed25519: bad private key length: " + strconv.Itoa(l))
|
||||||
|
}
|
||||||
|
|
||||||
|
h := sha512.New()
|
||||||
|
h.Write(privateKey[:32])
|
||||||
|
|
||||||
|
var digest1, messageDigest, hramDigest [64]byte
|
||||||
|
var expandedSecretKey [32]byte
|
||||||
|
h.Sum(digest1[:0])
|
||||||
|
copy(expandedSecretKey[:], digest1[:])
|
||||||
|
expandedSecretKey[0] &= 248
|
||||||
|
expandedSecretKey[31] &= 63
|
||||||
|
expandedSecretKey[31] |= 64
|
||||||
|
|
||||||
|
h.Reset()
|
||||||
|
h.Write(digest1[32:])
|
||||||
|
h.Write(message)
|
||||||
|
h.Sum(messageDigest[:0])
|
||||||
|
|
||||||
|
var messageDigestReduced [32]byte
|
||||||
|
edwards25519.ScReduce(&messageDigestReduced, &messageDigest)
|
||||||
|
var R edwards25519.ExtendedGroupElement
|
||||||
|
edwards25519.GeScalarMultBase(&R, &messageDigestReduced)
|
||||||
|
|
||||||
|
var encodedR [32]byte
|
||||||
|
R.ToBytes(&encodedR)
|
||||||
|
|
||||||
|
h.Reset()
|
||||||
|
h.Write(encodedR[:])
|
||||||
|
h.Write(privateKey[32:])
|
||||||
|
h.Write(message)
|
||||||
|
h.Sum(hramDigest[:0])
|
||||||
|
var hramDigestReduced [32]byte
|
||||||
|
edwards25519.ScReduce(&hramDigestReduced, &hramDigest)
|
||||||
|
|
||||||
|
var s [32]byte
|
||||||
|
edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)
|
||||||
|
|
||||||
|
signature := make([]byte, SignatureSize)
|
||||||
|
copy(signature[:], encodedR[:])
|
||||||
|
copy(signature[32:], s[:])
|
||||||
|
|
||||||
|
return signature
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify reports whether sig is a valid signature of message by publicKey. It
|
// Verify reports whether sig is a valid signature of message by publicKey. It
|
||||||
// will panic if len(publicKey) is not PublicKeySize.
|
// will panic if len(publicKey) is not PublicKeySize.
|
||||||
func Verify(publicKey PublicKey, message, sig []byte) bool {
|
func Verify(publicKey PublicKey, message, sig []byte) bool {
|
||||||
return ed25519.Verify(publicKey, message, sig)
|
if l := len(publicKey); l != PublicKeySize {
|
||||||
|
panic("ed25519: bad public key length: " + strconv.Itoa(l))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(sig) != SignatureSize || sig[63]&224 != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var A edwards25519.ExtendedGroupElement
|
||||||
|
var publicKeyBytes [32]byte
|
||||||
|
copy(publicKeyBytes[:], publicKey)
|
||||||
|
if !A.FromBytes(&publicKeyBytes) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
edwards25519.FeNeg(&A.X, &A.X)
|
||||||
|
edwards25519.FeNeg(&A.T, &A.T)
|
||||||
|
|
||||||
|
h := sha512.New()
|
||||||
|
h.Write(sig[:32])
|
||||||
|
h.Write(publicKey[:])
|
||||||
|
h.Write(message)
|
||||||
|
var digest [64]byte
|
||||||
|
h.Sum(digest[:0])
|
||||||
|
|
||||||
|
var hReduced [32]byte
|
||||||
|
edwards25519.ScReduce(&hReduced, &digest)
|
||||||
|
|
||||||
|
var R edwards25519.ProjectiveGroupElement
|
||||||
|
var s [32]byte
|
||||||
|
copy(s[:], sig[32:])
|
||||||
|
|
||||||
|
// https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in
|
||||||
|
// the range [0, order) in order to prevent signature malleability.
|
||||||
|
if !edwards25519.ScMinimal(&s) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s)
|
||||||
|
|
||||||
|
var checkR [32]byte
|
||||||
|
R.ToBytes(&checkR)
|
||||||
|
return bytes.Equal(sig[:32], checkR[:])
|
||||||
}
|
}
|
||||||
|
|||||||
74
vendor/golang.org/x/crypto/ed25519/ed25519_go113.go
generated
vendored
Normal file
74
vendor/golang.org/x/crypto/ed25519/ed25519_go113.go
generated
vendored
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
// 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
|
||||||
|
// +build go1.13
|
||||||
|
|
||||||
|
// Package ed25519 implements the Ed25519 signature algorithm. See
|
||||||
|
// https://ed25519.cr.yp.to/.
|
||||||
|
//
|
||||||
|
// These functions are also compatible with the “Ed25519” function defined in
|
||||||
|
// RFC 8032. However, unlike RFC 8032's formulation, this package's private key
|
||||||
|
// representation includes a public key suffix to make multiple signing
|
||||||
|
// operations with the same key more efficient. This package refers to the RFC
|
||||||
|
// 8032 private key as the “seed”.
|
||||||
|
//
|
||||||
|
// Beginning with Go 1.13, the functionality of this package was moved to the
|
||||||
|
// standard library as crypto/ed25519. This package only acts as a compatibility
|
||||||
|
// wrapper.
|
||||||
|
package ed25519
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ed25519"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// PublicKeySize is the size, in bytes, of public keys as used in this package.
|
||||||
|
PublicKeySize = 32
|
||||||
|
// PrivateKeySize is the size, in bytes, of private keys as used in this package.
|
||||||
|
PrivateKeySize = 64
|
||||||
|
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
|
||||||
|
SignatureSize = 64
|
||||||
|
// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
|
||||||
|
SeedSize = 32
|
||||||
|
)
|
||||||
|
|
||||||
|
// PublicKey is the type of Ed25519 public keys.
|
||||||
|
//
|
||||||
|
// This type is an alias for crypto/ed25519's PublicKey type.
|
||||||
|
// See the crypto/ed25519 package for the methods on this type.
|
||||||
|
type PublicKey = ed25519.PublicKey
|
||||||
|
|
||||||
|
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
|
||||||
|
//
|
||||||
|
// This type is an alias for crypto/ed25519's PrivateKey type.
|
||||||
|
// See the crypto/ed25519 package for the methods on this type.
|
||||||
|
type PrivateKey = ed25519.PrivateKey
|
||||||
|
|
||||||
|
// GenerateKey generates a public/private key pair using entropy from rand.
|
||||||
|
// If rand is nil, crypto/rand.Reader will be used.
|
||||||
|
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
|
||||||
|
return ed25519.GenerateKey(rand)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewKeyFromSeed calculates a private key from a seed. It will panic if
|
||||||
|
// len(seed) is not SeedSize. This function is provided for interoperability
|
||||||
|
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
|
||||||
|
// package.
|
||||||
|
func NewKeyFromSeed(seed []byte) PrivateKey {
|
||||||
|
return ed25519.NewKeyFromSeed(seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign signs the message with privateKey and returns a signature. It will
|
||||||
|
// panic if len(privateKey) is not PrivateKeySize.
|
||||||
|
func Sign(privateKey PrivateKey, message []byte) []byte {
|
||||||
|
return ed25519.Sign(privateKey, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify reports whether sig is a valid signature of message by publicKey. It
|
||||||
|
// will panic if len(publicKey) is not PublicKeySize.
|
||||||
|
func Verify(publicKey PublicKey, message, sig []byte) bool {
|
||||||
|
return ed25519.Verify(publicKey, message, sig)
|
||||||
|
}
|
||||||
1422
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
generated
vendored
Normal file
1422
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1793
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
generated
vendored
Normal file
1793
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -5,8 +5,9 @@
|
|||||||
//go:build !purego
|
//go:build !purego
|
||||||
// +build !purego
|
// +build !purego
|
||||||
|
|
||||||
// Package alias implements memory aliasing tests.
|
// Package subtle implements functions that are often useful in cryptographic
|
||||||
package alias
|
// code but require careful thought to use correctly.
|
||||||
|
package subtle // import "golang.org/x/crypto/internal/subtle"
|
||||||
|
|
||||||
import "unsafe"
|
import "unsafe"
|
||||||
|
|
||||||
@ -5,8 +5,9 @@
|
|||||||
//go:build purego
|
//go:build purego
|
||||||
// +build purego
|
// +build purego
|
||||||
|
|
||||||
// Package alias implements memory aliasing tests.
|
// Package subtle implements functions that are often useful in cryptographic
|
||||||
package alias
|
// code but require careful thought to use correctly.
|
||||||
|
package subtle // import "golang.org/x/crypto/internal/subtle"
|
||||||
|
|
||||||
// This is the Google App Engine standard variant based on reflect
|
// This is the Google App Engine standard variant based on reflect
|
||||||
// because the unsafe package and cgo are disallowed.
|
// because the unsafe package and cgo are disallowed.
|
||||||
@ -15,7 +15,7 @@
|
|||||||
// used with a fixed key in order to generate one-time keys from an nonce.
|
// used with a fixed key in order to generate one-time keys from an nonce.
|
||||||
// However, in this package AES isn't used and the one-time key is specified
|
// However, in this package AES isn't used and the one-time key is specified
|
||||||
// directly.
|
// directly.
|
||||||
package poly1305
|
package poly1305 // import "golang.org/x/crypto/poly1305"
|
||||||
|
|
||||||
import "crypto/subtle"
|
import "crypto/subtle"
|
||||||
|
|
||||||
@ -279,6 +279,7 @@ const (
|
|||||||
// finalize completes the modular reduction of h and computes
|
// finalize completes the modular reduction of h and computes
|
||||||
//
|
//
|
||||||
// out = h + s mod 2¹²⁸
|
// out = h + s mod 2¹²⁸
|
||||||
|
//
|
||||||
func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) {
|
func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) {
|
||||||
h0, h1, h2 := h[0], h[1], h[2]
|
h0, h1, h2 := h[0], h[1], h[2]
|
||||||
|
|
||||||
@ -14,7 +14,6 @@ import (
|
|||||||
// updateVX is an assembly implementation of Poly1305 that uses vector
|
// updateVX is an assembly implementation of Poly1305 that uses vector
|
||||||
// instructions. It must only be called if the vector facility (vx) is
|
// instructions. It must only be called if the vector facility (vx) is
|
||||||
// available.
|
// available.
|
||||||
//
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func updateVX(state *macState, msg []byte)
|
func updateVX(state *macState, msg []byte)
|
||||||
|
|
||||||
@ -18,7 +18,7 @@
|
|||||||
// value. These limbs are, for the most part, zero extended and
|
// value. These limbs are, for the most part, zero extended and
|
||||||
// placed into 64-bit vector register elements. Each vector
|
// placed into 64-bit vector register elements. Each vector
|
||||||
// register is 128-bits wide and so holds 2 of these elements.
|
// register is 128-bits wide and so holds 2 of these elements.
|
||||||
// Using 26-bit limbs allows us plenty of headroom to accommodate
|
// Using 26-bit limbs allows us plenty of headroom to accomodate
|
||||||
// accumulations before and after multiplication without
|
// accumulations before and after multiplication without
|
||||||
// overflowing either 32-bits (before multiplication) or 64-bits
|
// overflowing either 32-bits (before multiplication) or 64-bits
|
||||||
// (after multiplication).
|
// (after multiplication).
|
||||||
89
vendor/golang.org/x/crypto/ssh/certs.go
generated
vendored
89
vendor/golang.org/x/crypto/ssh/certs.go
generated
vendored
@ -14,10 +14,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Certificate algorithm names from [PROTOCOL.certkeys]. These values can appear
|
// These constants from [PROTOCOL.certkeys] represent the algorithm names
|
||||||
// in Certificate.Type, PublicKey.Type, and ClientConfig.HostKeyAlgorithms.
|
// for certificate types supported by this package.
|
||||||
// Unlike key algorithm names, these are not passed to AlgorithmSigner and don't
|
|
||||||
// appear in the Signature.Format field.
|
|
||||||
const (
|
const (
|
||||||
CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com"
|
CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com"
|
||||||
CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com"
|
CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com"
|
||||||
@ -27,21 +25,6 @@ const (
|
|||||||
CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com"
|
CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com"
|
||||||
CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com"
|
CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com"
|
||||||
CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com"
|
CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com"
|
||||||
|
|
||||||
// CertAlgoRSASHA256v01 and CertAlgoRSASHA512v01 can't appear as a
|
|
||||||
// Certificate.Type (or PublicKey.Type), but only in
|
|
||||||
// ClientConfig.HostKeyAlgorithms.
|
|
||||||
CertAlgoRSASHA256v01 = "rsa-sha2-256-cert-v01@openssh.com"
|
|
||||||
CertAlgoRSASHA512v01 = "rsa-sha2-512-cert-v01@openssh.com"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Deprecated: use CertAlgoRSAv01.
|
|
||||||
CertSigAlgoRSAv01 = CertAlgoRSAv01
|
|
||||||
// Deprecated: use CertAlgoRSASHA256v01.
|
|
||||||
CertSigAlgoRSASHA2256v01 = CertAlgoRSASHA256v01
|
|
||||||
// Deprecated: use CertAlgoRSASHA512v01.
|
|
||||||
CertSigAlgoRSASHA2512v01 = CertAlgoRSASHA512v01
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Certificate types distinguish between host and user
|
// Certificate types distinguish between host and user
|
||||||
@ -251,7 +234,7 @@ type algorithmOpenSSHCertSigner struct {
|
|||||||
// private key is held by signer. It returns an error if the public key in cert
|
// private key is held by signer. It returns an error if the public key in cert
|
||||||
// doesn't match the key used by signer.
|
// doesn't match the key used by signer.
|
||||||
func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) {
|
func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) {
|
||||||
if !bytes.Equal(cert.Key.Marshal(), signer.PublicKey().Marshal()) {
|
if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 {
|
||||||
return nil, errors.New("ssh: signer and cert have different public key")
|
return nil, errors.New("ssh: signer and cert have different public key")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,16 +423,6 @@ func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
|
|||||||
}
|
}
|
||||||
c.SignatureKey = authority.PublicKey()
|
c.SignatureKey = authority.PublicKey()
|
||||||
|
|
||||||
// Default to KeyAlgoRSASHA512 for ssh-rsa signers.
|
|
||||||
if v, ok := authority.(AlgorithmSigner); ok && v.PublicKey().Type() == KeyAlgoRSA {
|
|
||||||
sig, err := v.SignWithAlgorithm(rand, c.bytesForSigning(), KeyAlgoRSASHA512)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
c.Signature = sig
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
sig, err := authority.Sign(rand, c.bytesForSigning())
|
sig, err := authority.Sign(rand, c.bytesForSigning())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -458,42 +431,26 @@ func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// certKeyAlgoNames is a mapping from known certificate algorithm names to the
|
var certAlgoNames = map[string]string{
|
||||||
// corresponding public key signature algorithm.
|
KeyAlgoRSA: CertAlgoRSAv01,
|
||||||
//
|
KeyAlgoDSA: CertAlgoDSAv01,
|
||||||
// This map must be kept in sync with the one in agent/client.go.
|
KeyAlgoECDSA256: CertAlgoECDSA256v01,
|
||||||
var certKeyAlgoNames = map[string]string{
|
KeyAlgoECDSA384: CertAlgoECDSA384v01,
|
||||||
CertAlgoRSAv01: KeyAlgoRSA,
|
KeyAlgoECDSA521: CertAlgoECDSA521v01,
|
||||||
CertAlgoRSASHA256v01: KeyAlgoRSASHA256,
|
KeyAlgoSKECDSA256: CertAlgoSKECDSA256v01,
|
||||||
CertAlgoRSASHA512v01: KeyAlgoRSASHA512,
|
KeyAlgoED25519: CertAlgoED25519v01,
|
||||||
CertAlgoDSAv01: KeyAlgoDSA,
|
KeyAlgoSKED25519: CertAlgoSKED25519v01,
|
||||||
CertAlgoECDSA256v01: KeyAlgoECDSA256,
|
|
||||||
CertAlgoECDSA384v01: KeyAlgoECDSA384,
|
|
||||||
CertAlgoECDSA521v01: KeyAlgoECDSA521,
|
|
||||||
CertAlgoSKECDSA256v01: KeyAlgoSKECDSA256,
|
|
||||||
CertAlgoED25519v01: KeyAlgoED25519,
|
|
||||||
CertAlgoSKED25519v01: KeyAlgoSKED25519,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// underlyingAlgo returns the signature algorithm associated with algo (which is
|
// certToPrivAlgo returns the underlying algorithm for a certificate algorithm.
|
||||||
// an advertised or negotiated public key or host key algorithm). These are
|
// Panics if a non-certificate algorithm is passed.
|
||||||
// usually the same, except for certificate algorithms.
|
func certToPrivAlgo(algo string) string {
|
||||||
func underlyingAlgo(algo string) string {
|
for privAlgo, pubAlgo := range certAlgoNames {
|
||||||
if a, ok := certKeyAlgoNames[algo]; ok {
|
if pubAlgo == algo {
|
||||||
return a
|
return privAlgo
|
||||||
}
|
|
||||||
return algo
|
|
||||||
}
|
|
||||||
|
|
||||||
// certificateAlgo returns the certificate algorithms that uses the provided
|
|
||||||
// underlying signature algorithm.
|
|
||||||
func certificateAlgo(algo string) (certAlgo string, ok bool) {
|
|
||||||
for certName, algoName := range certKeyAlgoNames {
|
|
||||||
if algoName == algo {
|
|
||||||
return certName, true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "", false
|
panic("unknown cert algorithm")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cert *Certificate) bytesForSigning() []byte {
|
func (cert *Certificate) bytesForSigning() []byte {
|
||||||
@ -537,13 +494,13 @@ func (c *Certificate) Marshal() []byte {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type returns the certificate algorithm name. It is part of the PublicKey interface.
|
// Type returns the key name. It is part of the PublicKey interface.
|
||||||
func (c *Certificate) Type() string {
|
func (c *Certificate) Type() string {
|
||||||
certName, ok := certificateAlgo(c.Key.Type())
|
algo, ok := certAlgoNames[c.Key.Type()]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("unknown certificate type for key type " + c.Key.Type())
|
panic("unknown cert key type " + c.Key.Type())
|
||||||
}
|
}
|
||||||
return certName
|
return algo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify verifies a signature against the certificate's public
|
// Verify verifies a signature against the certificate's public
|
||||||
|
|||||||
13
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
13
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
@ -15,9 +15,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"hash"
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
"golang.org/x/crypto/chacha20"
|
"golang.org/x/crypto/chacha20"
|
||||||
"golang.org/x/crypto/internal/poly1305"
|
"golang.org/x/crypto/poly1305"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -393,10 +394,6 @@ func (c *gcmCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error)
|
|||||||
}
|
}
|
||||||
c.incIV()
|
c.incIV()
|
||||||
|
|
||||||
if len(plain) == 0 {
|
|
||||||
return nil, errors.New("ssh: empty packet")
|
|
||||||
}
|
|
||||||
|
|
||||||
padding := plain[0]
|
padding := plain[0]
|
||||||
if padding < 4 {
|
if padding < 4 {
|
||||||
// padding is a byte, so it automatically satisfies
|
// padding is a byte, so it automatically satisfies
|
||||||
@ -496,7 +493,7 @@ func (c *cbcCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error)
|
|||||||
// data, to make distinguishing between
|
// data, to make distinguishing between
|
||||||
// failing MAC and failing length check more
|
// failing MAC and failing length check more
|
||||||
// difficult.
|
// difficult.
|
||||||
io.CopyN(io.Discard, r, int64(c.oracleCamouflage))
|
io.CopyN(ioutil.Discard, r, int64(c.oracleCamouflage))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p, err
|
return p, err
|
||||||
@ -713,10 +710,6 @@ func (c *chacha20Poly1305Cipher) readCipherPacket(seqNum uint32, r io.Reader) ([
|
|||||||
plain := c.buf[4:contentEnd]
|
plain := c.buf[4:contentEnd]
|
||||||
s.XORKeyStream(plain, plain)
|
s.XORKeyStream(plain, plain)
|
||||||
|
|
||||||
if len(plain) == 0 {
|
|
||||||
return nil, errors.New("ssh: empty packet")
|
|
||||||
}
|
|
||||||
|
|
||||||
padding := plain[0]
|
padding := plain[0]
|
||||||
if padding < 4 {
|
if padding < 4 {
|
||||||
// padding is a byte, so it automatically satisfies
|
// padding is a byte, so it automatically satisfies
|
||||||
|
|||||||
18
vendor/golang.org/x/crypto/ssh/client.go
generated
vendored
18
vendor/golang.org/x/crypto/ssh/client.go
generated
vendored
@ -113,18 +113,14 @@ func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) e
|
|||||||
return c.clientAuthenticate(config)
|
return c.clientAuthenticate(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
// verifyHostKeySignature verifies the host key obtained in the key exchange.
|
// verifyHostKeySignature verifies the host key obtained in the key
|
||||||
// algo is the negotiated algorithm, and may be a certificate type.
|
// exchange.
|
||||||
func verifyHostKeySignature(hostKey PublicKey, algo string, result *kexResult) error {
|
func verifyHostKeySignature(hostKey PublicKey, result *kexResult) error {
|
||||||
sig, rest, ok := parseSignatureBody(result.Signature)
|
sig, rest, ok := parseSignatureBody(result.Signature)
|
||||||
if len(rest) > 0 || !ok {
|
if len(rest) > 0 || !ok {
|
||||||
return errors.New("ssh: signature parse error")
|
return errors.New("ssh: signature parse error")
|
||||||
}
|
}
|
||||||
|
|
||||||
if a := underlyingAlgo(algo); sig.Format != a {
|
|
||||||
return fmt.Errorf("ssh: invalid signature algorithm %q, expected %q", sig.Format, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
return hostKey.Verify(result.H, sig)
|
return hostKey.Verify(result.H, sig)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,11 +224,11 @@ type ClientConfig struct {
|
|||||||
// be used for the connection. If empty, a reasonable default is used.
|
// be used for the connection. If empty, a reasonable default is used.
|
||||||
ClientVersion string
|
ClientVersion string
|
||||||
|
|
||||||
// HostKeyAlgorithms lists the public key algorithms that the client will
|
// HostKeyAlgorithms lists the key types that the client will
|
||||||
// accept from the server for host key authentication, in order of
|
// accept from the server as host key, in order of
|
||||||
// preference. If empty, a reasonable default is used. Any
|
// preference. If empty, a reasonable default is used. Any
|
||||||
// string returned from a PublicKey.Type method may be used, or
|
// string returned from PublicKey.Type method may be used, or
|
||||||
// any of the CertAlgo and KeyAlgo constants.
|
// any of the CertAlgoXxxx and KeyAlgoXxxx constants.
|
||||||
HostKeyAlgorithms []string
|
HostKeyAlgorithms []string
|
||||||
|
|
||||||
// Timeout is the maximum amount of time for the TCP connection to establish.
|
// Timeout is the maximum amount of time for the TCP connection to establish.
|
||||||
|
|||||||
132
vendor/golang.org/x/crypto/ssh/client_auth.go
generated
vendored
132
vendor/golang.org/x/crypto/ssh/client_auth.go
generated
vendored
@ -9,7 +9,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type authResult int
|
type authResult int
|
||||||
@ -30,33 +29,6 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// The server may choose to send a SSH_MSG_EXT_INFO at this point (if we
|
|
||||||
// advertised willingness to receive one, which we always do) or not. See
|
|
||||||
// RFC 8308, Section 2.4.
|
|
||||||
extensions := make(map[string][]byte)
|
|
||||||
if len(packet) > 0 && packet[0] == msgExtInfo {
|
|
||||||
var extInfo extInfoMsg
|
|
||||||
if err := Unmarshal(packet, &extInfo); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
payload := extInfo.Payload
|
|
||||||
for i := uint32(0); i < extInfo.NumExtensions; i++ {
|
|
||||||
name, rest, ok := parseString(payload)
|
|
||||||
if !ok {
|
|
||||||
return parseError(msgExtInfo)
|
|
||||||
}
|
|
||||||
value, rest, ok := parseString(rest)
|
|
||||||
if !ok {
|
|
||||||
return parseError(msgExtInfo)
|
|
||||||
}
|
|
||||||
extensions[string(name)] = value
|
|
||||||
payload = rest
|
|
||||||
}
|
|
||||||
packet, err = c.transport.readPacket()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var serviceAccept serviceAcceptMsg
|
var serviceAccept serviceAcceptMsg
|
||||||
if err := Unmarshal(packet, &serviceAccept); err != nil {
|
if err := Unmarshal(packet, &serviceAccept); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -69,7 +41,7 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
|
|||||||
|
|
||||||
sessionID := c.transport.getSessionID()
|
sessionID := c.transport.getSessionID()
|
||||||
for auth := AuthMethod(new(noneAuth)); auth != nil; {
|
for auth := AuthMethod(new(noneAuth)); auth != nil; {
|
||||||
ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand, extensions)
|
ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -121,7 +93,7 @@ type AuthMethod interface {
|
|||||||
// If authentication is not successful, a []string of alternative
|
// If authentication is not successful, a []string of alternative
|
||||||
// method names is returned. If the slice is nil, it will be ignored
|
// method names is returned. If the slice is nil, it will be ignored
|
||||||
// and the previous set of possible methods will be reused.
|
// and the previous set of possible methods will be reused.
|
||||||
auth(session []byte, user string, p packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error)
|
auth(session []byte, user string, p packetConn, rand io.Reader) (authResult, []string, error)
|
||||||
|
|
||||||
// method returns the RFC 4252 method name.
|
// method returns the RFC 4252 method name.
|
||||||
method() string
|
method() string
|
||||||
@ -130,7 +102,7 @@ type AuthMethod interface {
|
|||||||
// "none" authentication, RFC 4252 section 5.2.
|
// "none" authentication, RFC 4252 section 5.2.
|
||||||
type noneAuth int
|
type noneAuth int
|
||||||
|
|
||||||
func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) {
|
func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
|
||||||
if err := c.writePacket(Marshal(&userAuthRequestMsg{
|
if err := c.writePacket(Marshal(&userAuthRequestMsg{
|
||||||
User: user,
|
User: user,
|
||||||
Service: serviceSSH,
|
Service: serviceSSH,
|
||||||
@ -150,7 +122,7 @@ func (n *noneAuth) method() string {
|
|||||||
// a function call, e.g. by prompting the user.
|
// a function call, e.g. by prompting the user.
|
||||||
type passwordCallback func() (password string, err error)
|
type passwordCallback func() (password string, err error)
|
||||||
|
|
||||||
func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) {
|
func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
|
||||||
type passwordAuthMsg struct {
|
type passwordAuthMsg struct {
|
||||||
User string `sshtype:"50"`
|
User string `sshtype:"50"`
|
||||||
Service string
|
Service string
|
||||||
@ -217,46 +189,7 @@ func (cb publicKeyCallback) method() string {
|
|||||||
return "publickey"
|
return "publickey"
|
||||||
}
|
}
|
||||||
|
|
||||||
func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte) (as AlgorithmSigner, algo string) {
|
func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
|
||||||
keyFormat := signer.PublicKey().Type()
|
|
||||||
|
|
||||||
// Like in sendKexInit, if the public key implements AlgorithmSigner we
|
|
||||||
// assume it supports all algorithms, otherwise only the key format one.
|
|
||||||
as, ok := signer.(AlgorithmSigner)
|
|
||||||
if !ok {
|
|
||||||
return algorithmSignerWrapper{signer}, keyFormat
|
|
||||||
}
|
|
||||||
|
|
||||||
extPayload, ok := extensions["server-sig-algs"]
|
|
||||||
if !ok {
|
|
||||||
// If there is no "server-sig-algs" extension, fall back to the key
|
|
||||||
// format algorithm.
|
|
||||||
return as, keyFormat
|
|
||||||
}
|
|
||||||
|
|
||||||
// The server-sig-algs extension only carries underlying signature
|
|
||||||
// algorithm, but we are trying to select a protocol-level public key
|
|
||||||
// algorithm, which might be a certificate type. Extend the list of server
|
|
||||||
// supported algorithms to include the corresponding certificate algorithms.
|
|
||||||
serverAlgos := strings.Split(string(extPayload), ",")
|
|
||||||
for _, algo := range serverAlgos {
|
|
||||||
if certAlgo, ok := certificateAlgo(algo); ok {
|
|
||||||
serverAlgos = append(serverAlgos, certAlgo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
keyAlgos := algorithmsForKeyFormat(keyFormat)
|
|
||||||
algo, err := findCommon("public key signature algorithm", keyAlgos, serverAlgos)
|
|
||||||
if err != nil {
|
|
||||||
// If there is no overlap, try the key anyway with the key format
|
|
||||||
// algorithm, to support servers that fail to list all supported
|
|
||||||
// algorithms.
|
|
||||||
return as, keyFormat
|
|
||||||
}
|
|
||||||
return as, algo
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error) {
|
|
||||||
// Authentication is performed by sending an enquiry to test if a key is
|
// Authentication is performed by sending an enquiry to test if a key is
|
||||||
// acceptable to the remote. If the key is acceptable, the client will
|
// acceptable to the remote. If the key is acceptable, the client will
|
||||||
// attempt to authenticate with the valid key. If not the client will repeat
|
// attempt to authenticate with the valid key. If not the client will repeat
|
||||||
@ -268,10 +201,7 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
|
|||||||
}
|
}
|
||||||
var methods []string
|
var methods []string
|
||||||
for _, signer := range signers {
|
for _, signer := range signers {
|
||||||
pub := signer.PublicKey()
|
ok, err := validateKey(signer.PublicKey(), user, c)
|
||||||
as, algo := pickSignatureAlgorithm(signer, extensions)
|
|
||||||
|
|
||||||
ok, err := validateKey(pub, algo, user, c)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return authFailure, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
@ -279,13 +209,13 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub := signer.PublicKey()
|
||||||
pubKey := pub.Marshal()
|
pubKey := pub.Marshal()
|
||||||
data := buildDataSignedForAuth(session, userAuthRequestMsg{
|
sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{
|
||||||
User: user,
|
User: user,
|
||||||
Service: serviceSSH,
|
Service: serviceSSH,
|
||||||
Method: cb.method(),
|
Method: cb.method(),
|
||||||
}, algo, pubKey)
|
}, []byte(pub.Type()), pubKey))
|
||||||
sign, err := as.SignWithAlgorithm(rand, data, underlyingAlgo(algo))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return authFailure, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
@ -299,7 +229,7 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
|
|||||||
Service: serviceSSH,
|
Service: serviceSSH,
|
||||||
Method: cb.method(),
|
Method: cb.method(),
|
||||||
HasSig: true,
|
HasSig: true,
|
||||||
Algoname: algo,
|
Algoname: pub.Type(),
|
||||||
PubKey: pubKey,
|
PubKey: pubKey,
|
||||||
Sig: sig,
|
Sig: sig,
|
||||||
}
|
}
|
||||||
@ -336,25 +266,26 @@ func containsMethod(methods []string, method string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validateKey validates the key provided is acceptable to the server.
|
// validateKey validates the key provided is acceptable to the server.
|
||||||
func validateKey(key PublicKey, algo string, user string, c packetConn) (bool, error) {
|
func validateKey(key PublicKey, user string, c packetConn) (bool, error) {
|
||||||
pubKey := key.Marshal()
|
pubKey := key.Marshal()
|
||||||
msg := publickeyAuthMsg{
|
msg := publickeyAuthMsg{
|
||||||
User: user,
|
User: user,
|
||||||
Service: serviceSSH,
|
Service: serviceSSH,
|
||||||
Method: "publickey",
|
Method: "publickey",
|
||||||
HasSig: false,
|
HasSig: false,
|
||||||
Algoname: algo,
|
Algoname: key.Type(),
|
||||||
PubKey: pubKey,
|
PubKey: pubKey,
|
||||||
}
|
}
|
||||||
if err := c.writePacket(Marshal(&msg)); err != nil {
|
if err := c.writePacket(Marshal(&msg)); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return confirmKeyAck(key, algo, c)
|
return confirmKeyAck(key, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func confirmKeyAck(key PublicKey, algo string, c packetConn) (bool, error) {
|
func confirmKeyAck(key PublicKey, c packetConn) (bool, error) {
|
||||||
pubKey := key.Marshal()
|
pubKey := key.Marshal()
|
||||||
|
algoname := key.Type()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
packet, err := c.readPacket()
|
packet, err := c.readPacket()
|
||||||
@ -371,14 +302,14 @@ func confirmKeyAck(key PublicKey, algo string, c packetConn) (bool, error) {
|
|||||||
if err := Unmarshal(packet, &msg); err != nil {
|
if err := Unmarshal(packet, &msg); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
if msg.Algo != algo || !bytes.Equal(msg.PubKey, pubKey) {
|
if msg.Algo != algoname || !bytes.Equal(msg.PubKey, pubKey) {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
case msgUserAuthFailure:
|
case msgUserAuthFailure:
|
||||||
return false, nil
|
return false, nil
|
||||||
default:
|
default:
|
||||||
return false, unexpectedMessageError(msgUserAuthPubKeyOk, packet[0])
|
return false, unexpectedMessageError(msgUserAuthSuccess, packet[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -399,7 +330,6 @@ func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMet
|
|||||||
// along with a list of remaining authentication methods to try next and
|
// along with a list of remaining authentication methods to try next and
|
||||||
// an error if an unexpected response was received.
|
// an error if an unexpected response was received.
|
||||||
func handleAuthResponse(c packetConn) (authResult, []string, error) {
|
func handleAuthResponse(c packetConn) (authResult, []string, error) {
|
||||||
gotMsgExtInfo := false
|
|
||||||
for {
|
for {
|
||||||
packet, err := c.readPacket()
|
packet, err := c.readPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -411,12 +341,6 @@ func handleAuthResponse(c packetConn) (authResult, []string, error) {
|
|||||||
if err := handleBannerResponse(c, packet); err != nil {
|
if err := handleBannerResponse(c, packet); err != nil {
|
||||||
return authFailure, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
case msgExtInfo:
|
|
||||||
// Ignore post-authentication RFC 8308 extensions, once.
|
|
||||||
if gotMsgExtInfo {
|
|
||||||
return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0])
|
|
||||||
}
|
|
||||||
gotMsgExtInfo = true
|
|
||||||
case msgUserAuthFailure:
|
case msgUserAuthFailure:
|
||||||
var msg userAuthFailureMsg
|
var msg userAuthFailureMsg
|
||||||
if err := Unmarshal(packet, &msg); err != nil {
|
if err := Unmarshal(packet, &msg); err != nil {
|
||||||
@ -456,10 +380,10 @@ func handleBannerResponse(c packetConn, packet []byte) error {
|
|||||||
// disabling echoing (e.g. for passwords), and return all the answers.
|
// disabling echoing (e.g. for passwords), and return all the answers.
|
||||||
// Challenge may be called multiple times in a single session. After
|
// Challenge may be called multiple times in a single session. After
|
||||||
// successful authentication, the server may send a challenge with no
|
// successful authentication, the server may send a challenge with no
|
||||||
// questions, for which the name and instruction messages should be
|
// questions, for which the user and instruction messages should be
|
||||||
// printed. RFC 4256 section 3.3 details how the UI should behave for
|
// printed. RFC 4256 section 3.3 details how the UI should behave for
|
||||||
// both CLI and GUI environments.
|
// both CLI and GUI environments.
|
||||||
type KeyboardInteractiveChallenge func(name, instruction string, questions []string, echos []bool) (answers []string, err error)
|
type KeyboardInteractiveChallenge func(user, instruction string, questions []string, echos []bool) (answers []string, err error)
|
||||||
|
|
||||||
// KeyboardInteractive returns an AuthMethod using a prompt/response
|
// KeyboardInteractive returns an AuthMethod using a prompt/response
|
||||||
// sequence controlled by the server.
|
// sequence controlled by the server.
|
||||||
@ -471,7 +395,7 @@ func (cb KeyboardInteractiveChallenge) method() string {
|
|||||||
return "keyboard-interactive"
|
return "keyboard-interactive"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) {
|
func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
|
||||||
type initiateMsg struct {
|
type initiateMsg struct {
|
||||||
User string `sshtype:"50"`
|
User string `sshtype:"50"`
|
||||||
Service string
|
Service string
|
||||||
@ -488,7 +412,6 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
|
|||||||
return authFailure, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
gotMsgExtInfo := false
|
|
||||||
for {
|
for {
|
||||||
packet, err := c.readPacket()
|
packet, err := c.readPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -502,13 +425,6 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
|
|||||||
return authFailure, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
case msgExtInfo:
|
|
||||||
// Ignore post-authentication RFC 8308 extensions, once.
|
|
||||||
if gotMsgExtInfo {
|
|
||||||
return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0])
|
|
||||||
}
|
|
||||||
gotMsgExtInfo = true
|
|
||||||
continue
|
|
||||||
case msgUserAuthInfoRequest:
|
case msgUserAuthInfoRequest:
|
||||||
// OK
|
// OK
|
||||||
case msgUserAuthFailure:
|
case msgUserAuthFailure:
|
||||||
@ -549,7 +465,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
|
|||||||
return authFailure, nil, errors.New("ssh: extra data following keyboard-interactive pairs")
|
return authFailure, nil, errors.New("ssh: extra data following keyboard-interactive pairs")
|
||||||
}
|
}
|
||||||
|
|
||||||
answers, err := cb(msg.Name, msg.Instruction, prompts, echos)
|
answers, err := cb(msg.User, msg.Instruction, prompts, echos)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return authFailure, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
@ -581,9 +497,9 @@ type retryableAuthMethod struct {
|
|||||||
maxTries int
|
maxTries int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (ok authResult, methods []string, err error) {
|
func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok authResult, methods []string, err error) {
|
||||||
for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ {
|
for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ {
|
||||||
ok, methods, err = r.authMethod.auth(session, user, c, rand, extensions)
|
ok, methods, err = r.authMethod.auth(session, user, c, rand)
|
||||||
if ok != authFailure || err != nil { // either success, partial success or error terminate
|
if ok != authFailure || err != nil { // either success, partial success or error terminate
|
||||||
return ok, methods, err
|
return ok, methods, err
|
||||||
}
|
}
|
||||||
@ -626,7 +542,7 @@ type gssAPIWithMICCallback struct {
|
|||||||
target string
|
target string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *gssAPIWithMICCallback) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) {
|
func (g *gssAPIWithMICCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
|
||||||
m := &userAuthRequestMsg{
|
m := &userAuthRequestMsg{
|
||||||
User: user,
|
User: user,
|
||||||
Service: serviceSSH,
|
Service: serviceSSH,
|
||||||
|
|||||||
69
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
69
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
@ -10,7 +10,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
_ "crypto/sha1"
|
_ "crypto/sha1"
|
||||||
@ -45,11 +44,11 @@ var preferredCiphers = []string{
|
|||||||
// supportedKexAlgos specifies the supported key-exchange algorithms in
|
// supportedKexAlgos specifies the supported key-exchange algorithms in
|
||||||
// preference order.
|
// preference order.
|
||||||
var supportedKexAlgos = []string{
|
var supportedKexAlgos = []string{
|
||||||
kexAlgoCurve25519SHA256, kexAlgoCurve25519SHA256LibSSH,
|
kexAlgoCurve25519SHA256,
|
||||||
// P384 and P521 are not constant-time yet, but since we don't
|
// P384 and P521 are not constant-time yet, but since we don't
|
||||||
// reuse ephemeral keys, using them for ECDH should be OK.
|
// reuse ephemeral keys, using them for ECDH should be OK.
|
||||||
kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
|
kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
|
||||||
kexAlgoDH14SHA256, kexAlgoDH14SHA1, kexAlgoDH1SHA1,
|
kexAlgoDH14SHA1, kexAlgoDH1SHA1,
|
||||||
}
|
}
|
||||||
|
|
||||||
// serverForbiddenKexAlgos contains key exchange algorithms, that are forbidden
|
// serverForbiddenKexAlgos contains key exchange algorithms, that are forbidden
|
||||||
@ -62,20 +61,18 @@ var serverForbiddenKexAlgos = map[string]struct{}{
|
|||||||
// preferredKexAlgos specifies the default preference for key-exchange algorithms
|
// preferredKexAlgos specifies the default preference for key-exchange algorithms
|
||||||
// in preference order.
|
// in preference order.
|
||||||
var preferredKexAlgos = []string{
|
var preferredKexAlgos = []string{
|
||||||
kexAlgoCurve25519SHA256, kexAlgoCurve25519SHA256LibSSH,
|
kexAlgoCurve25519SHA256,
|
||||||
kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
|
kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
|
||||||
kexAlgoDH14SHA256, kexAlgoDH14SHA1,
|
kexAlgoDH14SHA1,
|
||||||
}
|
}
|
||||||
|
|
||||||
// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
|
// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
|
||||||
// of authenticating servers) in preference order.
|
// of authenticating servers) in preference order.
|
||||||
var supportedHostKeyAlgos = []string{
|
var supportedHostKeyAlgos = []string{
|
||||||
CertAlgoRSASHA512v01, CertAlgoRSASHA256v01,
|
|
||||||
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
|
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
|
||||||
CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01,
|
CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01,
|
||||||
|
|
||||||
KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
|
KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
|
||||||
KeyAlgoRSASHA512, KeyAlgoRSASHA256,
|
|
||||||
KeyAlgoRSA, KeyAlgoDSA,
|
KeyAlgoRSA, KeyAlgoDSA,
|
||||||
|
|
||||||
KeyAlgoED25519,
|
KeyAlgoED25519,
|
||||||
@ -90,49 +87,21 @@ var supportedMACs = []string{
|
|||||||
|
|
||||||
var supportedCompressions = []string{compressionNone}
|
var supportedCompressions = []string{compressionNone}
|
||||||
|
|
||||||
// hashFuncs keeps the mapping of supported signature algorithms to their
|
// hashFuncs keeps the mapping of supported algorithms to their respective
|
||||||
// respective hashes needed for signing and verification.
|
// hashes needed for signature verification.
|
||||||
var hashFuncs = map[string]crypto.Hash{
|
var hashFuncs = map[string]crypto.Hash{
|
||||||
KeyAlgoRSA: crypto.SHA1,
|
KeyAlgoRSA: crypto.SHA1,
|
||||||
KeyAlgoRSASHA256: crypto.SHA256,
|
|
||||||
KeyAlgoRSASHA512: crypto.SHA512,
|
|
||||||
KeyAlgoDSA: crypto.SHA1,
|
KeyAlgoDSA: crypto.SHA1,
|
||||||
KeyAlgoECDSA256: crypto.SHA256,
|
KeyAlgoECDSA256: crypto.SHA256,
|
||||||
KeyAlgoECDSA384: crypto.SHA384,
|
KeyAlgoECDSA384: crypto.SHA384,
|
||||||
KeyAlgoECDSA521: crypto.SHA512,
|
KeyAlgoECDSA521: crypto.SHA512,
|
||||||
// KeyAlgoED25519 doesn't pre-hash.
|
CertAlgoRSAv01: crypto.SHA1,
|
||||||
KeyAlgoSKECDSA256: crypto.SHA256,
|
CertAlgoDSAv01: crypto.SHA1,
|
||||||
KeyAlgoSKED25519: crypto.SHA256,
|
CertAlgoECDSA256v01: crypto.SHA256,
|
||||||
|
CertAlgoECDSA384v01: crypto.SHA384,
|
||||||
|
CertAlgoECDSA521v01: crypto.SHA512,
|
||||||
}
|
}
|
||||||
|
|
||||||
// algorithmsForKeyFormat returns the supported signature algorithms for a given
|
|
||||||
// public key format (PublicKey.Type), in order of preference. See RFC 8332,
|
|
||||||
// Section 2. See also the note in sendKexInit on backwards compatibility.
|
|
||||||
func algorithmsForKeyFormat(keyFormat string) []string {
|
|
||||||
switch keyFormat {
|
|
||||||
case KeyAlgoRSA:
|
|
||||||
return []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoRSA}
|
|
||||||
case CertAlgoRSAv01:
|
|
||||||
return []string{CertAlgoRSASHA256v01, CertAlgoRSASHA512v01, CertAlgoRSAv01}
|
|
||||||
default:
|
|
||||||
return []string{keyFormat}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// supportedPubKeyAuthAlgos specifies the supported client public key
|
|
||||||
// authentication algorithms. Note that this doesn't include certificate types
|
|
||||||
// since those use the underlying algorithm. This list is sent to the client if
|
|
||||||
// it supports the server-sig-algs extension. Order is irrelevant.
|
|
||||||
var supportedPubKeyAuthAlgos = []string{
|
|
||||||
KeyAlgoED25519,
|
|
||||||
KeyAlgoSKED25519, KeyAlgoSKECDSA256,
|
|
||||||
KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
|
|
||||||
KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoRSA,
|
|
||||||
KeyAlgoDSA,
|
|
||||||
}
|
|
||||||
|
|
||||||
var supportedPubKeyAuthAlgosList = strings.Join(supportedPubKeyAuthAlgos, ",")
|
|
||||||
|
|
||||||
// unexpectedMessageError results when the SSH message that we received didn't
|
// unexpectedMessageError results when the SSH message that we received didn't
|
||||||
// match what we wanted.
|
// match what we wanted.
|
||||||
func unexpectedMessageError(expected, got uint8) error {
|
func unexpectedMessageError(expected, got uint8) error {
|
||||||
@ -177,11 +146,6 @@ func (a *directionAlgorithms) rekeyBytes() int64 {
|
|||||||
return 1 << 30
|
return 1 << 30
|
||||||
}
|
}
|
||||||
|
|
||||||
var aeadCiphers = map[string]bool{
|
|
||||||
gcmCipherID: true,
|
|
||||||
chacha20Poly1305ID: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
type algorithms struct {
|
type algorithms struct {
|
||||||
kex string
|
kex string
|
||||||
hostKey string
|
hostKey string
|
||||||
@ -217,19 +181,15 @@ func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMs
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !aeadCiphers[ctos.Cipher] {
|
|
||||||
ctos.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
|
ctos.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if !aeadCiphers[stoc.Cipher] {
|
|
||||||
stoc.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
|
stoc.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ctos.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
|
ctos.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -312,9 +272,8 @@ func (c *Config) SetDefaults() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// buildDataSignedForAuth returns the data that is signed in order to prove
|
// buildDataSignedForAuth returns the data that is signed in order to prove
|
||||||
// possession of a private key. See RFC 4252, section 7. algo is the advertised
|
// possession of a private key. See RFC 4252, section 7.
|
||||||
// algorithm, and may be a certificate type.
|
func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte {
|
||||||
func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo string, pubKey []byte) []byte {
|
|
||||||
data := struct {
|
data := struct {
|
||||||
Session []byte
|
Session []byte
|
||||||
Type byte
|
Type byte
|
||||||
@ -322,7 +281,7 @@ func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo strin
|
|||||||
Service string
|
Service string
|
||||||
Method string
|
Method string
|
||||||
Sign bool
|
Sign bool
|
||||||
Algo string
|
Algo []byte
|
||||||
PubKey []byte
|
PubKey []byte
|
||||||
}{
|
}{
|
||||||
sessionID,
|
sessionID,
|
||||||
|
|||||||
1
vendor/golang.org/x/crypto/ssh/doc.go
generated
vendored
1
vendor/golang.org/x/crypto/ssh/doc.go
generated
vendored
@ -12,7 +12,6 @@ the multiplexed nature of SSH is exposed to users that wish to support
|
|||||||
others.
|
others.
|
||||||
|
|
||||||
References:
|
References:
|
||||||
|
|
||||||
[PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD
|
[PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD
|
||||||
[SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
|
[SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
|
||||||
|
|
||||||
|
|||||||
140
vendor/golang.org/x/crypto/ssh/handshake.go
generated
vendored
140
vendor/golang.org/x/crypto/ssh/handshake.go
generated
vendored
@ -63,8 +63,6 @@ type handshakeTransport struct {
|
|||||||
sentInitPacket []byte
|
sentInitPacket []byte
|
||||||
sentInitMsg *kexInitMsg
|
sentInitMsg *kexInitMsg
|
||||||
pendingPackets [][]byte // Used when a key exchange is in progress.
|
pendingPackets [][]byte // Used when a key exchange is in progress.
|
||||||
writePacketsLeft uint32
|
|
||||||
writeBytesLeft int64
|
|
||||||
|
|
||||||
// If the read loop wants to schedule a kex, it pings this
|
// If the read loop wants to schedule a kex, it pings this
|
||||||
// channel, and the write loop will send out a kex
|
// channel, and the write loop will send out a kex
|
||||||
@ -74,7 +72,6 @@ type handshakeTransport struct {
|
|||||||
// If the other side requests or confirms a kex, its kexInit
|
// If the other side requests or confirms a kex, its kexInit
|
||||||
// packet is sent here for the write loop to find it.
|
// packet is sent here for the write loop to find it.
|
||||||
startKex chan *pendingKex
|
startKex chan *pendingKex
|
||||||
kexLoopDone chan struct{} // closed (with writeError non-nil) when kexLoop exits
|
|
||||||
|
|
||||||
// data for host key checking
|
// data for host key checking
|
||||||
hostKeyCallback HostKeyCallback
|
hostKeyCallback HostKeyCallback
|
||||||
@ -89,10 +86,12 @@ type handshakeTransport struct {
|
|||||||
// Algorithms agreed in the last key exchange.
|
// Algorithms agreed in the last key exchange.
|
||||||
algorithms *algorithms
|
algorithms *algorithms
|
||||||
|
|
||||||
// Counters exclusively owned by readLoop.
|
|
||||||
readPacketsLeft uint32
|
readPacketsLeft uint32
|
||||||
readBytesLeft int64
|
readBytesLeft int64
|
||||||
|
|
||||||
|
writePacketsLeft uint32
|
||||||
|
writeBytesLeft int64
|
||||||
|
|
||||||
// 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
|
||||||
}
|
}
|
||||||
@ -109,8 +108,7 @@ func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion,
|
|||||||
clientVersion: clientVersion,
|
clientVersion: clientVersion,
|
||||||
incoming: make(chan []byte, chanSize),
|
incoming: make(chan []byte, chanSize),
|
||||||
requestKex: make(chan struct{}, 1),
|
requestKex: make(chan struct{}, 1),
|
||||||
startKex: make(chan *pendingKex),
|
startKex: make(chan *pendingKex, 1),
|
||||||
kexLoopDone: make(chan struct{}),
|
|
||||||
|
|
||||||
config: config,
|
config: config,
|
||||||
}
|
}
|
||||||
@ -342,17 +340,16 @@ write:
|
|||||||
t.mu.Unlock()
|
t.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unblock reader.
|
|
||||||
t.conn.Close()
|
|
||||||
|
|
||||||
// drain startKex channel. We don't service t.requestKex
|
// drain startKex channel. We don't service t.requestKex
|
||||||
// because nobody does blocking sends there.
|
// because nobody does blocking sends there.
|
||||||
for request := range t.startKex {
|
go func() {
|
||||||
request.done <- t.getWriteError()
|
for init := range t.startKex {
|
||||||
|
init.done <- t.writeError
|
||||||
}
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
// Mark that the loop is done so that Close can return.
|
// Unblock reader.
|
||||||
close(t.kexLoopDone)
|
t.conn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// The protocol uses uint32 for packet counters, so we can't let them
|
// The protocol uses uint32 for packet counters, so we can't let them
|
||||||
@ -458,38 +455,14 @@ func (t *handshakeTransport) sendKexInit() error {
|
|||||||
}
|
}
|
||||||
io.ReadFull(rand.Reader, msg.Cookie[:])
|
io.ReadFull(rand.Reader, msg.Cookie[:])
|
||||||
|
|
||||||
isServer := len(t.hostKeys) > 0
|
if len(t.hostKeys) > 0 {
|
||||||
if isServer {
|
|
||||||
for _, k := range t.hostKeys {
|
for _, k := range t.hostKeys {
|
||||||
// If k is an AlgorithmSigner, presume it supports all signature algorithms
|
msg.ServerHostKeyAlgos = append(
|
||||||
// associated with the key format. (Ideally AlgorithmSigner would have a
|
msg.ServerHostKeyAlgos, k.PublicKey().Type())
|
||||||
// method to advertise supported algorithms, but it doesn't. This means that
|
|
||||||
// adding support for a new algorithm is a breaking change, as we will
|
|
||||||
// immediately negotiate it even if existing implementations don't support
|
|
||||||
// it. If that ever happens, we'll have to figure something out.)
|
|
||||||
// If k is not an AlgorithmSigner, we can only assume it only supports the
|
|
||||||
// algorithms that matches the key format. (This means that Sign can't pick
|
|
||||||
// a different default.)
|
|
||||||
keyFormat := k.PublicKey().Type()
|
|
||||||
if _, ok := k.(AlgorithmSigner); ok {
|
|
||||||
msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, algorithmsForKeyFormat(keyFormat)...)
|
|
||||||
} else {
|
|
||||||
msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, keyFormat)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} 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
|
|
||||||
// algorithms the server supports for public key authentication. See RFC
|
|
||||||
// 8308, Section 2.1.
|
|
||||||
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")
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
packet := Marshal(msg)
|
packet := Marshal(msg)
|
||||||
|
|
||||||
// writePacket destroys the contents, so save a copy.
|
// writePacket destroys the contents, so save a copy.
|
||||||
@ -548,16 +521,7 @@ func (t *handshakeTransport) writePacket(p []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *handshakeTransport) Close() error {
|
func (t *handshakeTransport) Close() error {
|
||||||
// Close the connection. This should cause the readLoop goroutine to wake up
|
return t.conn.Close()
|
||||||
// and close t.startKex, which will shut down kexLoop if running.
|
|
||||||
err := t.conn.Close()
|
|
||||||
|
|
||||||
// Wait for the kexLoop goroutine to complete.
|
|
||||||
// At that point we know that the readLoop goroutine is complete too,
|
|
||||||
// because kexLoop itself waits for readLoop to close the startKex channel.
|
|
||||||
<-t.kexLoopDone
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
||||||
@ -618,17 +582,16 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
|||||||
|
|
||||||
var result *kexResult
|
var result *kexResult
|
||||||
if len(t.hostKeys) > 0 {
|
if len(t.hostKeys) > 0 {
|
||||||
result, err = t.server(kex, &magics)
|
result, err = t.server(kex, t.algorithms, &magics)
|
||||||
} else {
|
} else {
|
||||||
result, err = t.client(kex, &magics)
|
result, err = t.client(kex, t.algorithms, &magics)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
firstKeyExchange := t.sessionID == nil
|
if t.sessionID == nil {
|
||||||
if firstKeyExchange {
|
|
||||||
t.sessionID = result.H
|
t.sessionID = result.H
|
||||||
}
|
}
|
||||||
result.SessionID = t.sessionID
|
result.SessionID = t.sessionID
|
||||||
@ -639,24 +602,6 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
|||||||
if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
|
if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// On the server side, after the first SSH_MSG_NEWKEYS, send a SSH_MSG_EXT_INFO
|
|
||||||
// message with the server-sig-algs extension if the client supports it. See
|
|
||||||
// RFC 8308, Sections 2.4 and 3.1.
|
|
||||||
if !isClient && firstKeyExchange && contains(clientInit.KexAlgos, "ext-info-c") {
|
|
||||||
extInfo := &extInfoMsg{
|
|
||||||
NumExtensions: 1,
|
|
||||||
Payload: make([]byte, 0, 4+15+4+len(supportedPubKeyAuthAlgosList)),
|
|
||||||
}
|
|
||||||
extInfo.Payload = appendInt(extInfo.Payload, len("server-sig-algs"))
|
|
||||||
extInfo.Payload = append(extInfo.Payload, "server-sig-algs"...)
|
|
||||||
extInfo.Payload = appendInt(extInfo.Payload, len(supportedPubKeyAuthAlgosList))
|
|
||||||
extInfo.Payload = append(extInfo.Payload, supportedPubKeyAuthAlgosList...)
|
|
||||||
if err := t.conn.writePacket(Marshal(extInfo)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if packet, err := t.conn.readPacket(); err != nil {
|
if packet, err := t.conn.readPacket(); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if packet[0] != msgNewKeys {
|
} else if packet[0] != msgNewKeys {
|
||||||
@ -666,52 +611,19 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// algorithmSignerWrapper is an AlgorithmSigner that only supports the default
|
func (t *handshakeTransport) server(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) {
|
||||||
// key format algorithm.
|
var hostKey Signer
|
||||||
//
|
for _, k := range t.hostKeys {
|
||||||
// This is technically a violation of the AlgorithmSigner interface, but it
|
if algs.hostKey == k.PublicKey().Type() {
|
||||||
// should be unreachable given where we use this. Anyway, at least it returns an
|
hostKey = k
|
||||||
// error instead of panicing or producing an incorrect signature.
|
}
|
||||||
type algorithmSignerWrapper struct {
|
|
||||||
Signer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a algorithmSignerWrapper) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
|
r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey)
|
||||||
if algorithm != underlyingAlgo(a.PublicKey().Type()) {
|
|
||||||
return nil, errors.New("ssh: internal error: algorithmSignerWrapper invoked with non-default algorithm")
|
|
||||||
}
|
|
||||||
return a.Sign(rand, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func pickHostKey(hostKeys []Signer, algo string) AlgorithmSigner {
|
|
||||||
for _, k := range hostKeys {
|
|
||||||
if algo == k.PublicKey().Type() {
|
|
||||||
return algorithmSignerWrapper{k}
|
|
||||||
}
|
|
||||||
k, ok := k.(AlgorithmSigner)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, a := range algorithmsForKeyFormat(k.PublicKey().Type()) {
|
|
||||||
if algo == a {
|
|
||||||
return k
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *handshakeTransport) server(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) {
|
|
||||||
hostKey := pickHostKey(t.hostKeys, t.algorithms.hostKey)
|
|
||||||
if hostKey == nil {
|
|
||||||
return nil, errors.New("ssh: internal error: negotiated unsupported signature type")
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey, t.algorithms.hostKey)
|
|
||||||
return r, err
|
return r, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *handshakeTransport) client(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) {
|
func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) {
|
||||||
result, err := kex.Client(t.conn, t.config.Rand, magics)
|
result, err := kex.Client(t.conn, t.config.Rand, magics)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -722,7 +634,7 @@ func (t *handshakeTransport) client(kex kexAlgorithm, magics *handshakeMagics) (
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := verifyHostKeySignature(hostKey, t.algorithms.hostKey, result); err != nil {
|
if err := verifyHostKeySignature(hostKey, result); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
170
vendor/golang.org/x/crypto/ssh/kex.go
generated
vendored
170
vendor/golang.org/x/crypto/ssh/kex.go
generated
vendored
@ -22,12 +22,10 @@ import (
|
|||||||
const (
|
const (
|
||||||
kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1"
|
kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1"
|
||||||
kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
|
kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
|
||||||
kexAlgoDH14SHA256 = "diffie-hellman-group14-sha256"
|
|
||||||
kexAlgoECDH256 = "ecdh-sha2-nistp256"
|
kexAlgoECDH256 = "ecdh-sha2-nistp256"
|
||||||
kexAlgoECDH384 = "ecdh-sha2-nistp384"
|
kexAlgoECDH384 = "ecdh-sha2-nistp384"
|
||||||
kexAlgoECDH521 = "ecdh-sha2-nistp521"
|
kexAlgoECDH521 = "ecdh-sha2-nistp521"
|
||||||
kexAlgoCurve25519SHA256LibSSH = "curve25519-sha256@libssh.org"
|
kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org"
|
||||||
kexAlgoCurve25519SHA256 = "curve25519-sha256"
|
|
||||||
|
|
||||||
// For the following kex only the client half contains a production
|
// For the following kex only the client half contains a production
|
||||||
// ready implementation. The server half only consists of a minimal
|
// ready implementation. The server half only consists of a minimal
|
||||||
@ -77,9 +75,8 @@ func (m *handshakeMagics) write(w io.Writer) {
|
|||||||
// kexAlgorithm abstracts different key exchange algorithms.
|
// kexAlgorithm abstracts different key exchange algorithms.
|
||||||
type kexAlgorithm interface {
|
type kexAlgorithm interface {
|
||||||
// Server runs server-side key agreement, signing the result
|
// Server runs server-side key agreement, signing the result
|
||||||
// with a hostkey. algo is the negotiated algorithm, and may
|
// with a hostkey.
|
||||||
// be a certificate type.
|
Server(p packetConn, rand io.Reader, magics *handshakeMagics, s Signer) (*kexResult, error)
|
||||||
Server(p packetConn, rand io.Reader, magics *handshakeMagics, s AlgorithmSigner, algo string) (*kexResult, error)
|
|
||||||
|
|
||||||
// Client runs the client-side key agreement. Caller is
|
// Client runs the client-side key agreement. Caller is
|
||||||
// responsible for verifying the host key signature.
|
// responsible for verifying the host key signature.
|
||||||
@ -89,7 +86,6 @@ type kexAlgorithm interface {
|
|||||||
// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement.
|
// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement.
|
||||||
type dhGroup struct {
|
type dhGroup struct {
|
||||||
g, p, pMinus1 *big.Int
|
g, p, pMinus1 *big.Int
|
||||||
hashFunc crypto.Hash
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
|
func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
|
||||||
@ -100,6 +96,8 @@ func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
|
func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
|
||||||
|
hashFunc := crypto.SHA1
|
||||||
|
|
||||||
var x *big.Int
|
var x *big.Int
|
||||||
for {
|
for {
|
||||||
var err error
|
var err error
|
||||||
@ -134,7 +132,7 @@ func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handsha
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
h := group.hashFunc.New()
|
h := hashFunc.New()
|
||||||
magics.write(h)
|
magics.write(h)
|
||||||
writeString(h, kexDHReply.HostKey)
|
writeString(h, kexDHReply.HostKey)
|
||||||
writeInt(h, X)
|
writeInt(h, X)
|
||||||
@ -148,11 +146,12 @@ func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handsha
|
|||||||
K: K,
|
K: K,
|
||||||
HostKey: kexDHReply.HostKey,
|
HostKey: kexDHReply.HostKey,
|
||||||
Signature: kexDHReply.Signature,
|
Signature: kexDHReply.Signature,
|
||||||
Hash: group.hashFunc,
|
Hash: crypto.SHA1,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) {
|
func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
|
||||||
|
hashFunc := crypto.SHA1
|
||||||
packet, err := c.readPacket()
|
packet, err := c.readPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -180,7 +179,7 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha
|
|||||||
|
|
||||||
hostKeyBytes := priv.PublicKey().Marshal()
|
hostKeyBytes := priv.PublicKey().Marshal()
|
||||||
|
|
||||||
h := group.hashFunc.New()
|
h := hashFunc.New()
|
||||||
magics.write(h)
|
magics.write(h)
|
||||||
writeString(h, hostKeyBytes)
|
writeString(h, hostKeyBytes)
|
||||||
writeInt(h, kexDHInit.X)
|
writeInt(h, kexDHInit.X)
|
||||||
@ -194,7 +193,7 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha
|
|||||||
|
|
||||||
// H is already a hash, but the hostkey signing will apply its
|
// H is already a hash, but the hostkey signing will apply its
|
||||||
// own key-specific hash algorithm.
|
// own key-specific hash algorithm.
|
||||||
sig, err := signAndMarshal(priv, randSource, H, algo)
|
sig, err := signAndMarshal(priv, randSource, H)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -212,7 +211,7 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha
|
|||||||
K: K,
|
K: K,
|
||||||
HostKey: hostKeyBytes,
|
HostKey: hostKeyBytes,
|
||||||
Signature: sig,
|
Signature: sig,
|
||||||
Hash: group.hashFunc,
|
Hash: crypto.SHA1,
|
||||||
}, err
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +314,7 @@ func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) {
|
func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
|
||||||
packet, err := c.readPacket()
|
packet, err := c.readPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -360,7 +359,7 @@ func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, p
|
|||||||
|
|
||||||
// H is already a hash, but the hostkey signing will apply its
|
// H is already a hash, but the hostkey signing will apply its
|
||||||
// own key-specific hash algorithm.
|
// own key-specific hash algorithm.
|
||||||
sig, err := signAndMarshal(priv, rand, H, algo)
|
sig, err := signAndMarshal(priv, rand, H)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -385,62 +384,39 @@ func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, p
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ecHash returns the hash to match the given elliptic curve, see RFC
|
|
||||||
// 5656, section 6.2.1
|
|
||||||
func ecHash(curve elliptic.Curve) crypto.Hash {
|
|
||||||
bitSize := curve.Params().BitSize
|
|
||||||
switch {
|
|
||||||
case bitSize <= 256:
|
|
||||||
return crypto.SHA256
|
|
||||||
case bitSize <= 384:
|
|
||||||
return crypto.SHA384
|
|
||||||
}
|
|
||||||
return crypto.SHA512
|
|
||||||
}
|
|
||||||
|
|
||||||
var kexAlgoMap = map[string]kexAlgorithm{}
|
var kexAlgoMap = map[string]kexAlgorithm{}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// This is the group called diffie-hellman-group1-sha1 in
|
// This is the group called diffie-hellman-group1-sha1 in RFC
|
||||||
// RFC 4253 and Oakley Group 2 in RFC 2409.
|
// 4253 and Oakley Group 2 in RFC 2409.
|
||||||
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
|
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
|
||||||
kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
|
kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
|
||||||
g: new(big.Int).SetInt64(2),
|
g: new(big.Int).SetInt64(2),
|
||||||
p: p,
|
p: p,
|
||||||
pMinus1: new(big.Int).Sub(p, bigOne),
|
pMinus1: new(big.Int).Sub(p, bigOne),
|
||||||
hashFunc: crypto.SHA1,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This are the groups called diffie-hellman-group14-sha1 and
|
// This is the group called diffie-hellman-group14-sha1 in RFC
|
||||||
// diffie-hellman-group14-sha256 in RFC 4253 and RFC 8268,
|
// 4253 and Oakley Group 14 in RFC 3526.
|
||||||
// and Oakley Group 14 in RFC 3526.
|
|
||||||
p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
|
p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
|
||||||
group14 := &dhGroup{
|
|
||||||
|
kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
|
||||||
g: new(big.Int).SetInt64(2),
|
g: new(big.Int).SetInt64(2),
|
||||||
p: p,
|
p: p,
|
||||||
pMinus1: new(big.Int).Sub(p, bigOne),
|
pMinus1: new(big.Int).Sub(p, bigOne),
|
||||||
}
|
}
|
||||||
|
|
||||||
kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
|
|
||||||
g: group14.g, p: group14.p, pMinus1: group14.pMinus1,
|
|
||||||
hashFunc: crypto.SHA1,
|
|
||||||
}
|
|
||||||
kexAlgoMap[kexAlgoDH14SHA256] = &dhGroup{
|
|
||||||
g: group14.g, p: group14.p, pMinus1: group14.pMinus1,
|
|
||||||
hashFunc: crypto.SHA256,
|
|
||||||
}
|
|
||||||
|
|
||||||
kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()}
|
kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()}
|
||||||
kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()}
|
kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()}
|
||||||
kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()}
|
kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()}
|
||||||
kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{}
|
kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{}
|
||||||
kexAlgoMap[kexAlgoCurve25519SHA256LibSSH] = &curve25519sha256{}
|
|
||||||
kexAlgoMap[kexAlgoDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1}
|
kexAlgoMap[kexAlgoDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1}
|
||||||
kexAlgoMap[kexAlgoDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256}
|
kexAlgoMap[kexAlgoDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256}
|
||||||
}
|
}
|
||||||
|
|
||||||
// curve25519sha256 implements the curve25519-sha256 (formerly known as
|
// curve25519sha256 implements the curve25519-sha256@libssh.org key
|
||||||
// curve25519-sha256@libssh.org) key exchange method, as described in RFC 8731.
|
// agreement protocol, as described in
|
||||||
|
// https://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt
|
||||||
type curve25519sha256 struct{}
|
type curve25519sha256 struct{}
|
||||||
|
|
||||||
type curve25519KeyPair struct {
|
type curve25519KeyPair struct {
|
||||||
@ -510,7 +486,7 @@ func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handsh
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) {
|
func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
|
||||||
packet, err := c.readPacket()
|
packet, err := c.readPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -551,7 +527,7 @@ func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handsh
|
|||||||
|
|
||||||
H := h.Sum(nil)
|
H := h.Sum(nil)
|
||||||
|
|
||||||
sig, err := signAndMarshal(priv, rand, H, algo)
|
sig, err := signAndMarshal(priv, rand, H)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -577,6 +553,7 @@ func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handsh
|
|||||||
// diffie-hellman-group-exchange-sha256 key agreement protocols,
|
// diffie-hellman-group-exchange-sha256 key agreement protocols,
|
||||||
// as described in RFC 4419
|
// as described in RFC 4419
|
||||||
type dhGEXSHA struct {
|
type dhGEXSHA struct {
|
||||||
|
g, p *big.Int
|
||||||
hashFunc crypto.Hash
|
hashFunc crypto.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,7 +563,14 @@ const (
|
|||||||
dhGroupExchangeMaximumBits = 8192
|
dhGroupExchangeMaximumBits = 8192
|
||||||
)
|
)
|
||||||
|
|
||||||
func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
|
func (gex *dhGEXSHA) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
|
||||||
|
if theirPublic.Sign() <= 0 || theirPublic.Cmp(gex.p) >= 0 {
|
||||||
|
return nil, fmt.Errorf("ssh: DH parameter out of bounds")
|
||||||
|
}
|
||||||
|
return new(big.Int).Exp(theirPublic, myPrivate, gex.p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gex dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
|
||||||
// Send GexRequest
|
// Send GexRequest
|
||||||
kexDHGexRequest := kexDHGexRequestMsg{
|
kexDHGexRequest := kexDHGexRequestMsg{
|
||||||
MinBits: dhGroupExchangeMinimumBits,
|
MinBits: dhGroupExchangeMinimumBits,
|
||||||
@ -603,29 +587,35 @@ func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshak
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var msg kexDHGexGroupMsg
|
var kexDHGexGroup kexDHGexGroupMsg
|
||||||
if err = Unmarshal(packet, &msg); err != nil {
|
if err = Unmarshal(packet, &kexDHGexGroup); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// reject if p's bit length < dhGroupExchangeMinimumBits or > dhGroupExchangeMaximumBits
|
// reject if p's bit length < dhGroupExchangeMinimumBits or > dhGroupExchangeMaximumBits
|
||||||
if msg.P.BitLen() < dhGroupExchangeMinimumBits || msg.P.BitLen() > dhGroupExchangeMaximumBits {
|
if kexDHGexGroup.P.BitLen() < dhGroupExchangeMinimumBits || kexDHGexGroup.P.BitLen() > dhGroupExchangeMaximumBits {
|
||||||
return nil, fmt.Errorf("ssh: server-generated gex p is out of range (%d bits)", msg.P.BitLen())
|
return nil, fmt.Errorf("ssh: server-generated gex p is out of range (%d bits)", kexDHGexGroup.P.BitLen())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if g is safe by verifying that 1 < g < p-1
|
gex.p = kexDHGexGroup.P
|
||||||
pMinusOne := new(big.Int).Sub(msg.P, bigOne)
|
gex.g = kexDHGexGroup.G
|
||||||
if msg.G.Cmp(bigOne) <= 0 || msg.G.Cmp(pMinusOne) >= 0 {
|
|
||||||
|
// Check if g is safe by verifing that g > 1 and g < p - 1
|
||||||
|
one := big.NewInt(1)
|
||||||
|
var pMinusOne = &big.Int{}
|
||||||
|
pMinusOne.Sub(gex.p, one)
|
||||||
|
if gex.g.Cmp(one) != 1 && gex.g.Cmp(pMinusOne) != -1 {
|
||||||
return nil, fmt.Errorf("ssh: server provided gex g is not safe")
|
return nil, fmt.Errorf("ssh: server provided gex g is not safe")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send GexInit
|
// Send GexInit
|
||||||
pHalf := new(big.Int).Rsh(msg.P, 1)
|
var pHalf = &big.Int{}
|
||||||
|
pHalf.Rsh(gex.p, 1)
|
||||||
x, err := rand.Int(randSource, pHalf)
|
x, err := rand.Int(randSource, pHalf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
X := new(big.Int).Exp(msg.G, x, msg.P)
|
X := new(big.Int).Exp(gex.g, x, gex.p)
|
||||||
kexDHGexInit := kexDHGexInitMsg{
|
kexDHGexInit := kexDHGexInitMsg{
|
||||||
X: X,
|
X: X,
|
||||||
}
|
}
|
||||||
@ -644,13 +634,13 @@ func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshak
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if kexDHGexReply.Y.Cmp(bigOne) <= 0 || kexDHGexReply.Y.Cmp(pMinusOne) >= 0 {
|
kInt, err := gex.diffieHellman(kexDHGexReply.Y, x)
|
||||||
return nil, errors.New("ssh: DH parameter out of bounds")
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
kInt := new(big.Int).Exp(kexDHGexReply.Y, x, msg.P)
|
|
||||||
|
|
||||||
// Check if k is safe by verifying that k > 1 and k < p - 1
|
// Check if k is safe by verifing that k > 1 and k < p - 1
|
||||||
if kInt.Cmp(bigOne) <= 0 || kInt.Cmp(pMinusOne) >= 0 {
|
if kInt.Cmp(one) != 1 && kInt.Cmp(pMinusOne) != -1 {
|
||||||
return nil, fmt.Errorf("ssh: derived k is not safe")
|
return nil, fmt.Errorf("ssh: derived k is not safe")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -660,8 +650,8 @@ func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshak
|
|||||||
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
|
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
|
||||||
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
|
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
|
||||||
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
|
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
|
||||||
writeInt(h, msg.P)
|
writeInt(h, gex.p)
|
||||||
writeInt(h, msg.G)
|
writeInt(h, gex.g)
|
||||||
writeInt(h, X)
|
writeInt(h, X)
|
||||||
writeInt(h, kexDHGexReply.Y)
|
writeInt(h, kexDHGexReply.Y)
|
||||||
K := make([]byte, intLength(kInt))
|
K := make([]byte, intLength(kInt))
|
||||||
@ -680,7 +670,7 @@ func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshak
|
|||||||
// Server half implementation of the Diffie Hellman Key Exchange with SHA1 and SHA256.
|
// Server half implementation of the Diffie Hellman Key Exchange with SHA1 and SHA256.
|
||||||
//
|
//
|
||||||
// This is a minimal implementation to satisfy the automated tests.
|
// This is a minimal implementation to satisfy the automated tests.
|
||||||
func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) {
|
func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
|
||||||
// Receive GexRequest
|
// Receive GexRequest
|
||||||
packet, err := c.readPacket()
|
packet, err := c.readPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -691,17 +681,35 @@ func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshake
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// smoosh the user's preferred size into our own limits
|
||||||
|
if kexDHGexRequest.PreferedBits > dhGroupExchangeMaximumBits {
|
||||||
|
kexDHGexRequest.PreferedBits = dhGroupExchangeMaximumBits
|
||||||
|
}
|
||||||
|
if kexDHGexRequest.PreferedBits < dhGroupExchangeMinimumBits {
|
||||||
|
kexDHGexRequest.PreferedBits = dhGroupExchangeMinimumBits
|
||||||
|
}
|
||||||
|
// fix min/max if they're inconsistent. technically, we could just pout
|
||||||
|
// and hang up, but there's no harm in giving them the benefit of the
|
||||||
|
// doubt and just picking a bitsize for them.
|
||||||
|
if kexDHGexRequest.MinBits > kexDHGexRequest.PreferedBits {
|
||||||
|
kexDHGexRequest.MinBits = kexDHGexRequest.PreferedBits
|
||||||
|
}
|
||||||
|
if kexDHGexRequest.MaxBits < kexDHGexRequest.PreferedBits {
|
||||||
|
kexDHGexRequest.MaxBits = kexDHGexRequest.PreferedBits
|
||||||
|
}
|
||||||
|
|
||||||
// Send GexGroup
|
// Send GexGroup
|
||||||
// This is the group called diffie-hellman-group14-sha1 in RFC
|
// This is the group called diffie-hellman-group14-sha1 in RFC
|
||||||
// 4253 and Oakley Group 14 in RFC 3526.
|
// 4253 and Oakley Group 14 in RFC 3526.
|
||||||
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
|
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
|
||||||
g := big.NewInt(2)
|
gex.p = p
|
||||||
|
gex.g = big.NewInt(2)
|
||||||
|
|
||||||
msg := &kexDHGexGroupMsg{
|
kexDHGexGroup := kexDHGexGroupMsg{
|
||||||
P: p,
|
P: gex.p,
|
||||||
G: g,
|
G: gex.g,
|
||||||
}
|
}
|
||||||
if err := c.writePacket(Marshal(msg)); err != nil {
|
if err := c.writePacket(Marshal(&kexDHGexGroup)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -715,19 +723,19 @@ func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshake
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
pHalf := new(big.Int).Rsh(p, 1)
|
var pHalf = &big.Int{}
|
||||||
|
pHalf.Rsh(gex.p, 1)
|
||||||
|
|
||||||
y, err := rand.Int(randSource, pHalf)
|
y, err := rand.Int(randSource, pHalf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
Y := new(big.Int).Exp(g, y, p)
|
|
||||||
|
|
||||||
pMinusOne := new(big.Int).Sub(p, bigOne)
|
Y := new(big.Int).Exp(gex.g, y, gex.p)
|
||||||
if kexDHGexInit.X.Cmp(bigOne) <= 0 || kexDHGexInit.X.Cmp(pMinusOne) >= 0 {
|
kInt, err := gex.diffieHellman(kexDHGexInit.X, y)
|
||||||
return nil, errors.New("ssh: DH parameter out of bounds")
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
kInt := new(big.Int).Exp(kexDHGexInit.X, y, p)
|
|
||||||
|
|
||||||
hostKeyBytes := priv.PublicKey().Marshal()
|
hostKeyBytes := priv.PublicKey().Marshal()
|
||||||
|
|
||||||
@ -737,8 +745,8 @@ func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshake
|
|||||||
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
|
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
|
||||||
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
|
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
|
||||||
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
|
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
|
||||||
writeInt(h, p)
|
writeInt(h, gex.p)
|
||||||
writeInt(h, g)
|
writeInt(h, gex.g)
|
||||||
writeInt(h, kexDHGexInit.X)
|
writeInt(h, kexDHGexInit.X)
|
||||||
writeInt(h, Y)
|
writeInt(h, Y)
|
||||||
|
|
||||||
@ -750,7 +758,7 @@ func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshake
|
|||||||
|
|
||||||
// H is already a hash, but the hostkey signing will apply its
|
// H is already a hash, but the hostkey signing will apply its
|
||||||
// own key-specific hash algorithm.
|
// own key-specific hash algorithm.
|
||||||
sig, err := signAndMarshal(priv, randSource, H, algo)
|
sig, err := signAndMarshal(priv, randSource, H)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
143
vendor/golang.org/x/crypto/ssh/keys.go
generated
vendored
143
vendor/golang.org/x/crypto/ssh/keys.go
generated
vendored
@ -30,9 +30,8 @@ import (
|
|||||||
"golang.org/x/crypto/ssh/internal/bcrypt_pbkdf"
|
"golang.org/x/crypto/ssh/internal/bcrypt_pbkdf"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Public key algorithms names. These values can appear in PublicKey.Type,
|
// These constants represent the algorithm names for key types supported by this
|
||||||
// ClientConfig.HostKeyAlgorithms, Signature.Format, or as AlgorithmSigner
|
// package.
|
||||||
// arguments.
|
|
||||||
const (
|
const (
|
||||||
KeyAlgoRSA = "ssh-rsa"
|
KeyAlgoRSA = "ssh-rsa"
|
||||||
KeyAlgoDSA = "ssh-dss"
|
KeyAlgoDSA = "ssh-dss"
|
||||||
@ -42,21 +41,16 @@ const (
|
|||||||
KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
|
KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
|
||||||
KeyAlgoED25519 = "ssh-ed25519"
|
KeyAlgoED25519 = "ssh-ed25519"
|
||||||
KeyAlgoSKED25519 = "sk-ssh-ed25519@openssh.com"
|
KeyAlgoSKED25519 = "sk-ssh-ed25519@openssh.com"
|
||||||
|
|
||||||
// KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms, not
|
|
||||||
// public key formats, so they can't appear as a PublicKey.Type. The
|
|
||||||
// corresponding PublicKey.Type is KeyAlgoRSA. See RFC 8332, Section 2.
|
|
||||||
KeyAlgoRSASHA256 = "rsa-sha2-256"
|
|
||||||
KeyAlgoRSASHA512 = "rsa-sha2-512"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// These constants represent non-default signature algorithms that are supported
|
||||||
|
// as algorithm parameters to AlgorithmSigner.SignWithAlgorithm methods. See
|
||||||
|
// [PROTOCOL.agent] section 4.5.1 and
|
||||||
|
// https://tools.ietf.org/html/draft-ietf-curdle-rsa-sha2-10
|
||||||
const (
|
const (
|
||||||
// Deprecated: use KeyAlgoRSA.
|
SigAlgoRSA = "ssh-rsa"
|
||||||
SigAlgoRSA = KeyAlgoRSA
|
SigAlgoRSASHA2256 = "rsa-sha2-256"
|
||||||
// Deprecated: use KeyAlgoRSASHA256.
|
SigAlgoRSASHA2512 = "rsa-sha2-512"
|
||||||
SigAlgoRSASHA2256 = KeyAlgoRSASHA256
|
|
||||||
// Deprecated: use KeyAlgoRSASHA512.
|
|
||||||
SigAlgoRSASHA2512 = KeyAlgoRSASHA512
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// parsePubKey parses a public key of the given algorithm.
|
// parsePubKey parses a public key of the given algorithm.
|
||||||
@ -76,7 +70,7 @@ func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err err
|
|||||||
case KeyAlgoSKED25519:
|
case KeyAlgoSKED25519:
|
||||||
return parseSKEd25519(in)
|
return parseSKEd25519(in)
|
||||||
case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
|
case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
|
||||||
cert, err := parseCert(in, certKeyAlgoNames[algo])
|
cert, err := parseCert(in, certToPrivAlgo(algo))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -184,7 +178,7 @@ func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey
|
|||||||
return "", nil, nil, "", nil, io.EOF
|
return "", nil, nil, "", nil, io.EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseAuthorizedKey parses a public key from an authorized_keys
|
// ParseAuthorizedKeys parses a public key from an authorized_keys
|
||||||
// file used in OpenSSH according to the sshd(8) manual page.
|
// file used in OpenSSH according to the sshd(8) manual page.
|
||||||
func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) {
|
func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) {
|
||||||
for len(in) > 0 {
|
for len(in) > 0 {
|
||||||
@ -295,21 +289,18 @@ func MarshalAuthorizedKey(key PublicKey) []byte {
|
|||||||
return b.Bytes()
|
return b.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
// PublicKey represents a public key using an unspecified algorithm.
|
// PublicKey is an abstraction of different types of public keys.
|
||||||
//
|
|
||||||
// Some PublicKeys provided by this package also implement CryptoPublicKey.
|
|
||||||
type PublicKey interface {
|
type PublicKey interface {
|
||||||
// Type returns the key format name, e.g. "ssh-rsa".
|
// Type returns the key's type, e.g. "ssh-rsa".
|
||||||
Type() string
|
Type() string
|
||||||
|
|
||||||
// Marshal returns the serialized key data in SSH wire format, with the name
|
// Marshal returns the serialized key data in SSH wire format,
|
||||||
// prefix. To unmarshal the returned data, use the ParsePublicKey function.
|
// with the name prefix. To unmarshal the returned data, use
|
||||||
|
// the ParsePublicKey function.
|
||||||
Marshal() []byte
|
Marshal() []byte
|
||||||
|
|
||||||
// Verify that sig is a signature on the given data using this key. This
|
// Verify that sig is a signature on the given data using this
|
||||||
// method will hash the data appropriately first. sig.Format is allowed to
|
// key. This function will hash the data appropriately first.
|
||||||
// be any signature algorithm compatible with the key type, the caller
|
|
||||||
// should check if it has more stringent requirements.
|
|
||||||
Verify(data []byte, sig *Signature) error
|
Verify(data []byte, sig *Signature) error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,32 +311,25 @@ type CryptoPublicKey interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A Signer can create signatures that verify against a public key.
|
// A Signer can create signatures that verify against a public key.
|
||||||
//
|
|
||||||
// Some Signers provided by this package also implement AlgorithmSigner.
|
|
||||||
type Signer interface {
|
type Signer interface {
|
||||||
// PublicKey returns the associated PublicKey.
|
// PublicKey returns an associated PublicKey instance.
|
||||||
PublicKey() PublicKey
|
PublicKey() PublicKey
|
||||||
|
|
||||||
// Sign returns a signature for the given data. This method will hash the
|
// Sign returns raw signature for the given data. This method
|
||||||
// data appropriately first. The signature algorithm is expected to match
|
// will apply the hash specified for the keytype to the data.
|
||||||
// the key format returned by the PublicKey.Type method (and not to be any
|
|
||||||
// alternative algorithm supported by the key format).
|
|
||||||
Sign(rand io.Reader, data []byte) (*Signature, error)
|
Sign(rand io.Reader, data []byte) (*Signature, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// An AlgorithmSigner is a Signer that also supports specifying an algorithm to
|
// A AlgorithmSigner is a Signer that also supports specifying a specific
|
||||||
// use for signing.
|
// algorithm to use for signing.
|
||||||
//
|
|
||||||
// An AlgorithmSigner can't advertise the algorithms it supports, so it should
|
|
||||||
// be prepared to be invoked with every algorithm supported by the public key
|
|
||||||
// format.
|
|
||||||
type AlgorithmSigner interface {
|
type AlgorithmSigner interface {
|
||||||
Signer
|
Signer
|
||||||
|
|
||||||
// SignWithAlgorithm is like Signer.Sign, but allows specifying a desired
|
// SignWithAlgorithm is like Signer.Sign, but allows specification of a
|
||||||
// signing algorithm. Callers may pass an empty string for the algorithm in
|
// non-default signing algorithm. See the SigAlgo* constants in this
|
||||||
// which case the AlgorithmSigner will use a default algorithm. This default
|
// package for signature algorithms supported by this package. Callers may
|
||||||
// doesn't currently control any behavior in this package.
|
// pass an empty string for the algorithm in which case the AlgorithmSigner
|
||||||
|
// will use its default algorithm.
|
||||||
SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error)
|
SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,11 +381,17 @@ func (r *rsaPublicKey) Marshal() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error {
|
func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error {
|
||||||
supportedAlgos := algorithmsForKeyFormat(r.Type())
|
var hash crypto.Hash
|
||||||
if !contains(supportedAlgos, sig.Format) {
|
switch sig.Format {
|
||||||
|
case SigAlgoRSA:
|
||||||
|
hash = crypto.SHA1
|
||||||
|
case SigAlgoRSASHA2256:
|
||||||
|
hash = crypto.SHA256
|
||||||
|
case SigAlgoRSASHA2512:
|
||||||
|
hash = crypto.SHA512
|
||||||
|
default:
|
||||||
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type())
|
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type())
|
||||||
}
|
}
|
||||||
hash := hashFuncs[sig.Format]
|
|
||||||
h := hash.New()
|
h := hash.New()
|
||||||
h.Write(data)
|
h.Write(data)
|
||||||
digest := h.Sum(nil)
|
digest := h.Sum(nil)
|
||||||
@ -476,7 +466,7 @@ func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error {
|
|||||||
if sig.Format != k.Type() {
|
if sig.Format != k.Type() {
|
||||||
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
|
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
|
||||||
}
|
}
|
||||||
h := hashFuncs[sig.Format].New()
|
h := crypto.SHA1.New()
|
||||||
h.Write(data)
|
h.Write(data)
|
||||||
digest := h.Sum(nil)
|
digest := h.Sum(nil)
|
||||||
|
|
||||||
@ -509,7 +499,7 @@ func (k *dsaPrivateKey) PublicKey() PublicKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
|
func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
|
||||||
return k.SignWithAlgorithm(rand, data, k.PublicKey().Type())
|
return k.SignWithAlgorithm(rand, data, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
|
func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
|
||||||
@ -517,7 +507,7 @@ func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm
|
|||||||
return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm)
|
return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm)
|
||||||
}
|
}
|
||||||
|
|
||||||
h := hashFuncs[k.PublicKey().Type()].New()
|
h := crypto.SHA1.New()
|
||||||
h.Write(data)
|
h.Write(data)
|
||||||
digest := h.Sum(nil)
|
digest := h.Sum(nil)
|
||||||
r, s, err := dsa.Sign(rand, k.PrivateKey, digest)
|
r, s, err := dsa.Sign(rand, k.PrivateKey, digest)
|
||||||
@ -613,6 +603,19 @@ func supportedEllipticCurve(curve elliptic.Curve) bool {
|
|||||||
return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
|
return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ecHash returns the hash to match the given elliptic curve, see RFC
|
||||||
|
// 5656, section 6.2.1
|
||||||
|
func ecHash(curve elliptic.Curve) crypto.Hash {
|
||||||
|
bitSize := curve.Params().BitSize
|
||||||
|
switch {
|
||||||
|
case bitSize <= 256:
|
||||||
|
return crypto.SHA256
|
||||||
|
case bitSize <= 384:
|
||||||
|
return crypto.SHA384
|
||||||
|
}
|
||||||
|
return crypto.SHA512
|
||||||
|
}
|
||||||
|
|
||||||
// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1.
|
// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1.
|
||||||
func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
|
func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
|
||||||
var w struct {
|
var w struct {
|
||||||
@ -668,7 +671,7 @@ func (k *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
|
|||||||
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
|
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
|
||||||
}
|
}
|
||||||
|
|
||||||
h := hashFuncs[sig.Format].New()
|
h := ecHash(k.Curve).New()
|
||||||
h.Write(data)
|
h.Write(data)
|
||||||
digest := h.Sum(nil)
|
digest := h.Sum(nil)
|
||||||
|
|
||||||
@ -772,7 +775,7 @@ func (k *skECDSAPublicKey) Verify(data []byte, sig *Signature) error {
|
|||||||
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
|
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
|
||||||
}
|
}
|
||||||
|
|
||||||
h := hashFuncs[sig.Format].New()
|
h := ecHash(k.Curve).New()
|
||||||
h.Write([]byte(k.application))
|
h.Write([]byte(k.application))
|
||||||
appDigest := h.Sum(nil)
|
appDigest := h.Sum(nil)
|
||||||
|
|
||||||
@ -871,7 +874,7 @@ func (k *skEd25519PublicKey) Verify(data []byte, sig *Signature) error {
|
|||||||
return fmt.Errorf("invalid size %d for Ed25519 public key", l)
|
return fmt.Errorf("invalid size %d for Ed25519 public key", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
h := hashFuncs[sig.Format].New()
|
h := sha256.New()
|
||||||
h.Write([]byte(k.application))
|
h.Write([]byte(k.application))
|
||||||
appDigest := h.Sum(nil)
|
appDigest := h.Sum(nil)
|
||||||
|
|
||||||
@ -958,20 +961,44 @@ func (s *wrappedSigner) PublicKey() PublicKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
|
func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
|
||||||
return s.SignWithAlgorithm(rand, data, s.pubKey.Type())
|
return s.SignWithAlgorithm(rand, data, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *wrappedSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
|
func (s *wrappedSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
|
||||||
|
var hashFunc crypto.Hash
|
||||||
|
|
||||||
|
if _, ok := s.pubKey.(*rsaPublicKey); ok {
|
||||||
|
// RSA keys support a few hash functions determined by the requested signature algorithm
|
||||||
|
switch algorithm {
|
||||||
|
case "", SigAlgoRSA:
|
||||||
|
algorithm = SigAlgoRSA
|
||||||
|
hashFunc = crypto.SHA1
|
||||||
|
case SigAlgoRSASHA2256:
|
||||||
|
hashFunc = crypto.SHA256
|
||||||
|
case SigAlgoRSASHA2512:
|
||||||
|
hashFunc = crypto.SHA512
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The only supported algorithm for all other key types is the same as the type of the key
|
||||||
if algorithm == "" {
|
if algorithm == "" {
|
||||||
algorithm = s.pubKey.Type()
|
algorithm = s.pubKey.Type()
|
||||||
|
} else if algorithm != s.pubKey.Type() {
|
||||||
|
return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm)
|
||||||
}
|
}
|
||||||
|
|
||||||
supportedAlgos := algorithmsForKeyFormat(s.pubKey.Type())
|
switch key := s.pubKey.(type) {
|
||||||
if !contains(supportedAlgos, algorithm) {
|
case *dsaPublicKey:
|
||||||
return nil, fmt.Errorf("ssh: unsupported signature algorithm %q for key format %q", algorithm, s.pubKey.Type())
|
hashFunc = crypto.SHA1
|
||||||
|
case *ecdsaPublicKey:
|
||||||
|
hashFunc = ecHash(key.Curve)
|
||||||
|
case ed25519PublicKey:
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("ssh: unsupported key type %T", key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hashFunc := hashFuncs[algorithm]
|
|
||||||
var digest []byte
|
var digest []byte
|
||||||
if hashFunc != 0 {
|
if hashFunc != 0 {
|
||||||
h := hashFunc.New()
|
h := hashFunc.New()
|
||||||
|
|||||||
17
vendor/golang.org/x/crypto/ssh/messages.go
generated
vendored
17
vendor/golang.org/x/crypto/ssh/messages.go
generated
vendored
@ -68,7 +68,7 @@ type kexInitMsg struct {
|
|||||||
|
|
||||||
// See RFC 4253, section 8.
|
// See RFC 4253, section 8.
|
||||||
|
|
||||||
// Diffie-Hellman
|
// Diffie-Helman
|
||||||
const msgKexDHInit = 30
|
const msgKexDHInit = 30
|
||||||
|
|
||||||
type kexDHInitMsg struct {
|
type kexDHInitMsg struct {
|
||||||
@ -141,14 +141,6 @@ type serviceAcceptMsg struct {
|
|||||||
Service string `sshtype:"6"`
|
Service string `sshtype:"6"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// See RFC 8308, section 2.3
|
|
||||||
const msgExtInfo = 7
|
|
||||||
|
|
||||||
type extInfoMsg struct {
|
|
||||||
NumExtensions uint32 `sshtype:"7"`
|
|
||||||
Payload []byte `ssh:"rest"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// See RFC 4252, section 5.
|
// See RFC 4252, section 5.
|
||||||
const msgUserAuthRequest = 50
|
const msgUserAuthRequest = 50
|
||||||
|
|
||||||
@ -188,9 +180,9 @@ const msgUserAuthInfoRequest = 60
|
|||||||
const msgUserAuthInfoResponse = 61
|
const msgUserAuthInfoResponse = 61
|
||||||
|
|
||||||
type userAuthInfoRequestMsg struct {
|
type userAuthInfoRequestMsg struct {
|
||||||
Name string `sshtype:"60"`
|
User string `sshtype:"60"`
|
||||||
Instruction string
|
Instruction string
|
||||||
Language string
|
DeprecatedLanguage string
|
||||||
NumPrompts uint32
|
NumPrompts uint32
|
||||||
Prompts []byte `ssh:"rest"`
|
Prompts []byte `ssh:"rest"`
|
||||||
}
|
}
|
||||||
@ -790,8 +782,6 @@ func decode(packet []byte) (interface{}, error) {
|
|||||||
msg = new(serviceRequestMsg)
|
msg = new(serviceRequestMsg)
|
||||||
case msgServiceAccept:
|
case msgServiceAccept:
|
||||||
msg = new(serviceAcceptMsg)
|
msg = new(serviceAcceptMsg)
|
||||||
case msgExtInfo:
|
|
||||||
msg = new(extInfoMsg)
|
|
||||||
case msgKexInit:
|
case msgKexInit:
|
||||||
msg = new(kexInitMsg)
|
msg = new(kexInitMsg)
|
||||||
case msgKexDHInit:
|
case msgKexDHInit:
|
||||||
@ -853,7 +843,6 @@ var packetTypeNames = map[byte]string{
|
|||||||
msgDisconnect: "disconnectMsg",
|
msgDisconnect: "disconnectMsg",
|
||||||
msgServiceRequest: "serviceRequestMsg",
|
msgServiceRequest: "serviceRequestMsg",
|
||||||
msgServiceAccept: "serviceAcceptMsg",
|
msgServiceAccept: "serviceAcceptMsg",
|
||||||
msgExtInfo: "extInfoMsg",
|
|
||||||
msgKexInit: "kexInitMsg",
|
msgKexInit: "kexInitMsg",
|
||||||
msgKexDHInit: "kexDHInitMsg",
|
msgKexDHInit: "kexDHInitMsg",
|
||||||
msgKexDHReply: "kexDHReplyMsg",
|
msgKexDHReply: "kexDHReplyMsg",
|
||||||
|
|||||||
69
vendor/golang.org/x/crypto/ssh/server.go
generated
vendored
69
vendor/golang.org/x/crypto/ssh/server.go
generated
vendored
@ -68,16 +68,8 @@ type ServerConfig struct {
|
|||||||
|
|
||||||
// NoClientAuth is true if clients are allowed to connect without
|
// NoClientAuth is true if clients are allowed to connect without
|
||||||
// authenticating.
|
// authenticating.
|
||||||
// To determine NoClientAuth at runtime, set NoClientAuth to true
|
|
||||||
// and the optional NoClientAuthCallback to a non-nil value.
|
|
||||||
NoClientAuth bool
|
NoClientAuth bool
|
||||||
|
|
||||||
// NoClientAuthCallback, if non-nil, is called when a user
|
|
||||||
// attempts to authenticate with auth method "none".
|
|
||||||
// NoClientAuth must also be set to true for this be used, or
|
|
||||||
// this func is unused.
|
|
||||||
NoClientAuthCallback func(ConnMetadata) (*Permissions, error)
|
|
||||||
|
|
||||||
// MaxAuthTries specifies the maximum number of authentication attempts
|
// MaxAuthTries specifies the maximum number of authentication attempts
|
||||||
// permitted per connection. If set to a negative number, the number of
|
// permitted per connection. If set to a negative number, the number of
|
||||||
// attempts are unlimited. If set to zero, the number of attempts are limited
|
// attempts are unlimited. If set to zero, the number of attempts are limited
|
||||||
@ -128,7 +120,7 @@ type ServerConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddHostKey adds a private key as a host key. If an existing host
|
// AddHostKey adds a private key as a host key. If an existing host
|
||||||
// key exists with the same public key format, it is replaced. Each server
|
// key exists with the same algorithm, it is overwritten. Each server
|
||||||
// config must have at least one host key.
|
// config must have at least one host key.
|
||||||
func (s *ServerConfig) AddHostKey(key Signer) {
|
func (s *ServerConfig) AddHostKey(key Signer) {
|
||||||
for i, k := range s.hostKeys {
|
for i, k := range s.hostKeys {
|
||||||
@ -220,10 +212,9 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha
|
|||||||
}
|
}
|
||||||
|
|
||||||
// signAndMarshal signs the data with the appropriate algorithm,
|
// signAndMarshal signs the data with the appropriate algorithm,
|
||||||
// and serializes the result in SSH wire format. algo is the negotiate
|
// and serializes the result in SSH wire format.
|
||||||
// algorithm and may be a certificate type.
|
func signAndMarshal(k Signer, rand io.Reader, data []byte) ([]byte, error) {
|
||||||
func signAndMarshal(k AlgorithmSigner, rand io.Reader, data []byte, algo string) ([]byte, error) {
|
sig, err := k.Sign(rand, data)
|
||||||
sig, err := k.SignWithAlgorithm(rand, data, underlyingAlgo(algo))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -291,6 +282,15 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
|
|||||||
return perms, err
|
return perms, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isAcceptableAlgo(algo string) bool {
|
||||||
|
switch algo {
|
||||||
|
case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoSKECDSA256, KeyAlgoED25519, KeyAlgoSKED25519,
|
||||||
|
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
|
func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
return errors.New("ssh: no address known for client, but source-address match required")
|
return errors.New("ssh: no address known for client, but source-address match required")
|
||||||
@ -454,12 +454,8 @@ userAuthLoop:
|
|||||||
switch userAuthReq.Method {
|
switch userAuthReq.Method {
|
||||||
case "none":
|
case "none":
|
||||||
if config.NoClientAuth {
|
if config.NoClientAuth {
|
||||||
if config.NoClientAuthCallback != nil {
|
|
||||||
perms, authErr = config.NoClientAuthCallback(s)
|
|
||||||
} else {
|
|
||||||
authErr = nil
|
authErr = nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// allow initial attempt of 'none' without penalty
|
// allow initial attempt of 'none' without penalty
|
||||||
if authFailures == 0 {
|
if authFailures == 0 {
|
||||||
@ -505,7 +501,7 @@ userAuthLoop:
|
|||||||
return nil, parseError(msgUserAuthRequest)
|
return nil, parseError(msgUserAuthRequest)
|
||||||
}
|
}
|
||||||
algo := string(algoBytes)
|
algo := string(algoBytes)
|
||||||
if !contains(supportedPubKeyAuthAlgos, underlyingAlgo(algo)) {
|
if !isAcceptableAlgo(algo) {
|
||||||
authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo)
|
authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -557,22 +553,16 @@ userAuthLoop:
|
|||||||
if !ok || len(payload) > 0 {
|
if !ok || len(payload) > 0 {
|
||||||
return nil, parseError(msgUserAuthRequest)
|
return nil, parseError(msgUserAuthRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the public key algo and signature algo
|
// Ensure the public key algo and signature algo
|
||||||
// are supported. Compare the private key
|
// are supported. Compare the private key
|
||||||
// algorithm name that corresponds to algo with
|
// algorithm name that corresponds to algo with
|
||||||
// sig.Format. This is usually the same, but
|
// sig.Format. This is usually the same, but
|
||||||
// for certs, the names differ.
|
// for certs, the names differ.
|
||||||
if !contains(supportedPubKeyAuthAlgos, sig.Format) {
|
if !isAcceptableAlgo(sig.Format) {
|
||||||
authErr = fmt.Errorf("ssh: algorithm %q not accepted", sig.Format)
|
authErr = fmt.Errorf("ssh: algorithm %q not accepted", sig.Format)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if underlyingAlgo(algo) != sig.Format {
|
signedData := buildDataSignedForAuth(sessionID, userAuthReq, algoBytes, pubKeyData)
|
||||||
authErr = fmt.Errorf("ssh: signature %q not compatible with selected algorithm %q", sig.Format, algo)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
signedData := buildDataSignedForAuth(sessionID, userAuthReq, algo, pubKeyData)
|
|
||||||
|
|
||||||
if err := pubKey.Verify(signedData, sig); err != nil {
|
if err := pubKey.Verify(signedData, sig); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -643,30 +633,6 @@ userAuthLoop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
authFailures++
|
authFailures++
|
||||||
if config.MaxAuthTries > 0 && authFailures >= config.MaxAuthTries {
|
|
||||||
// If we have hit the max attempts, don't bother sending the
|
|
||||||
// final SSH_MSG_USERAUTH_FAILURE message, since there are
|
|
||||||
// no more authentication methods which can be attempted,
|
|
||||||
// and this message may cause the client to re-attempt
|
|
||||||
// authentication while we send the disconnect message.
|
|
||||||
// Continue, and trigger the disconnect at the start of
|
|
||||||
// the loop.
|
|
||||||
//
|
|
||||||
// The SSH specification is somewhat confusing about this,
|
|
||||||
// RFC 4252 Section 5.1 requires each authentication failure
|
|
||||||
// be responded to with a respective SSH_MSG_USERAUTH_FAILURE
|
|
||||||
// message, but Section 4 says the server should disconnect
|
|
||||||
// after some number of attempts, but it isn't explicit which
|
|
||||||
// message should take precedence (i.e. should there be a failure
|
|
||||||
// message than a disconnect message, or if we are going to
|
|
||||||
// disconnect, should we only send that message.)
|
|
||||||
//
|
|
||||||
// Either way, OpenSSH disconnects immediately after the last
|
|
||||||
// failed authnetication attempt, and given they are typically
|
|
||||||
// considered the golden implementation it seems reasonable
|
|
||||||
// to match that behavior.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var failureMsg userAuthFailureMsg
|
var failureMsg userAuthFailureMsg
|
||||||
if config.PasswordCallback != nil {
|
if config.PasswordCallback != nil {
|
||||||
@ -704,7 +670,7 @@ type sshClientKeyboardInteractive struct {
|
|||||||
*connection
|
*connection
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *sshClientKeyboardInteractive) Challenge(name, instruction string, questions []string, echos []bool) (answers []string, err error) {
|
func (c *sshClientKeyboardInteractive) Challenge(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
|
||||||
if len(questions) != len(echos) {
|
if len(questions) != len(echos) {
|
||||||
return nil, errors.New("ssh: echos and questions must have equal length")
|
return nil, errors.New("ssh: echos and questions must have equal length")
|
||||||
}
|
}
|
||||||
@ -716,7 +682,6 @@ func (c *sshClientKeyboardInteractive) Challenge(name, instruction string, quest
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := c.transport.writePacket(Marshal(&userAuthInfoRequestMsg{
|
if err := c.transport.writePacket(Marshal(&userAuthInfoRequestMsg{
|
||||||
Name: name,
|
|
||||||
Instruction: instruction,
|
Instruction: instruction,
|
||||||
NumPrompts: uint32(len(questions)),
|
NumPrompts: uint32(len(questions)),
|
||||||
Prompts: prompts,
|
Prompts: prompts,
|
||||||
|
|||||||
8
vendor/golang.org/x/crypto/ssh/session.go
generated
vendored
8
vendor/golang.org/x/crypto/ssh/session.go
generated
vendored
@ -13,6 +13,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -84,7 +85,6 @@ const (
|
|||||||
IXANY = 39
|
IXANY = 39
|
||||||
IXOFF = 40
|
IXOFF = 40
|
||||||
IMAXBEL = 41
|
IMAXBEL = 41
|
||||||
IUTF8 = 42 // RFC 8160
|
|
||||||
ISIG = 50
|
ISIG = 50
|
||||||
ICANON = 51
|
ICANON = 51
|
||||||
XCASE = 52
|
XCASE = 52
|
||||||
@ -123,7 +123,7 @@ type Session struct {
|
|||||||
// output and error.
|
// output and error.
|
||||||
//
|
//
|
||||||
// If either is nil, Run connects the corresponding file
|
// If either is nil, Run connects the corresponding file
|
||||||
// descriptor to an instance of io.Discard. There is a
|
// descriptor to an instance of ioutil.Discard. There is a
|
||||||
// fixed amount of buffering that is shared for the two streams.
|
// fixed amount of buffering that is shared for the two streams.
|
||||||
// If either blocks it may eventually cause the remote
|
// If either blocks it may eventually cause the remote
|
||||||
// command to block.
|
// command to block.
|
||||||
@ -505,7 +505,7 @@ func (s *Session) stdout() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if s.Stdout == nil {
|
if s.Stdout == nil {
|
||||||
s.Stdout = io.Discard
|
s.Stdout = ioutil.Discard
|
||||||
}
|
}
|
||||||
s.copyFuncs = append(s.copyFuncs, func() error {
|
s.copyFuncs = append(s.copyFuncs, func() error {
|
||||||
_, err := io.Copy(s.Stdout, s.ch)
|
_, err := io.Copy(s.Stdout, s.ch)
|
||||||
@ -518,7 +518,7 @@ func (s *Session) stderr() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if s.Stderr == nil {
|
if s.Stderr == nil {
|
||||||
s.Stderr = io.Discard
|
s.Stderr = ioutil.Discard
|
||||||
}
|
}
|
||||||
s.copyFuncs = append(s.copyFuncs, func() error {
|
s.copyFuncs = append(s.copyFuncs, func() error {
|
||||||
_, err := io.Copy(s.Stderr, s.ch.Stderr())
|
_, err := io.Copy(s.Stderr, s.ch.Stderr())
|
||||||
|
|||||||
8
vendor/golang.org/x/crypto/ssh/transport.go
generated
vendored
8
vendor/golang.org/x/crypto/ssh/transport.go
generated
vendored
@ -238,19 +238,15 @@ var (
|
|||||||
// (to setup server->client keys) or clientKeys (for client->server keys).
|
// (to setup server->client keys) or clientKeys (for client->server keys).
|
||||||
func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) {
|
func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) {
|
||||||
cipherMode := cipherModes[algs.Cipher]
|
cipherMode := cipherModes[algs.Cipher]
|
||||||
|
macMode := macModes[algs.MAC]
|
||||||
|
|
||||||
iv := make([]byte, cipherMode.ivSize)
|
iv := make([]byte, cipherMode.ivSize)
|
||||||
key := make([]byte, cipherMode.keySize)
|
key := make([]byte, cipherMode.keySize)
|
||||||
|
macKey := make([]byte, macMode.keySize)
|
||||||
|
|
||||||
generateKeyMaterial(iv, d.ivTag, kex)
|
generateKeyMaterial(iv, d.ivTag, kex)
|
||||||
generateKeyMaterial(key, d.keyTag, kex)
|
generateKeyMaterial(key, d.keyTag, kex)
|
||||||
|
|
||||||
var macKey []byte
|
|
||||||
if !aeadCiphers[algs.Cipher] {
|
|
||||||
macMode := macModes[algs.MAC]
|
|
||||||
macKey = make([]byte, macMode.keySize)
|
|
||||||
generateKeyMaterial(macKey, d.macKeyTag, kex)
|
generateKeyMaterial(macKey, d.macKeyTag, kex)
|
||||||
}
|
|
||||||
|
|
||||||
return cipherModes[algs.Cipher].create(key, iv, macKey, algs)
|
return cipherModes[algs.Cipher].create(key, iv, macKey, algs)
|
||||||
}
|
}
|
||||||
|
|||||||
2
vendor/golang.org/x/net/html/parse.go
generated
vendored
2
vendor/golang.org/x/net/html/parse.go
generated
vendored
@ -184,7 +184,7 @@ func (p *parser) clearStackToContext(s scope) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseGenericRawTextElements implements the generic raw text element parsing
|
// parseGenericRawTextElement implements the generic raw text element parsing
|
||||||
// algorithm defined in 12.2.6.2.
|
// algorithm defined in 12.2.6.2.
|
||||||
// https://html.spec.whatwg.org/multipage/parsing.html#parsing-elements-that-contain-only-text
|
// https://html.spec.whatwg.org/multipage/parsing.html#parsing-elements-that-contain-only-text
|
||||||
// TODO: Since both RAWTEXT and RCDATA states are treated as tokenizer's part
|
// TODO: Since both RAWTEXT and RCDATA states are treated as tokenizer's part
|
||||||
|
|||||||
2
vendor/golang.org/x/net/http2/flow.go
generated
vendored
2
vendor/golang.org/x/net/http2/flow.go
generated
vendored
@ -18,7 +18,7 @@ type inflow struct {
|
|||||||
unsent int32
|
unsent int32
|
||||||
}
|
}
|
||||||
|
|
||||||
// set sets the initial window.
|
// init sets the initial window.
|
||||||
func (f *inflow) init(n int32) {
|
func (f *inflow) init(n int32) {
|
||||||
f.avail = n
|
f.avail = n
|
||||||
}
|
}
|
||||||
|
|||||||
2
vendor/golang.org/x/net/http2/hpack/hpack.go
generated
vendored
2
vendor/golang.org/x/net/http2/hpack/hpack.go
generated
vendored
@ -211,7 +211,7 @@ func (d *Decoder) at(i uint64) (hf HeaderField, ok bool) {
|
|||||||
return dt.ents[dt.len()-(int(i)-staticTable.len())], true
|
return dt.ents[dt.len()-(int(i)-staticTable.len())], true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode decodes an entire block.
|
// DecodeFull decodes an entire block.
|
||||||
//
|
//
|
||||||
// TODO: remove this method and make it incremental later? This is
|
// TODO: remove this method and make it incremental later? This is
|
||||||
// easier for debugging now.
|
// easier for debugging now.
|
||||||
|
|||||||
2
vendor/golang.org/x/net/http2/server.go
generated
vendored
2
vendor/golang.org/x/net/http2/server.go
generated
vendored
@ -2192,7 +2192,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
|
|||||||
tlsState = sc.tlsState
|
tlsState = sc.tlsState
|
||||||
}
|
}
|
||||||
|
|
||||||
needsContinue := rp.header.Get("Expect") == "100-continue"
|
needsContinue := httpguts.HeaderValuesContainsToken(rp.header["Expect"], "100-continue")
|
||||||
if needsContinue {
|
if needsContinue {
|
||||||
rp.header.Del("Expect")
|
rp.header.Del("Expect")
|
||||||
}
|
}
|
||||||
|
|||||||
2
vendor/golang.org/x/net/http2/transport.go
generated
vendored
2
vendor/golang.org/x/net/http2/transport.go
generated
vendored
@ -1569,7 +1569,7 @@ func (cs *clientStream) cleanupWriteRequest(err error) {
|
|||||||
close(cs.donec)
|
close(cs.donec)
|
||||||
}
|
}
|
||||||
|
|
||||||
// awaitOpenSlotForStream waits until len(streams) < maxConcurrentStreams.
|
// awaitOpenSlotForStreamLocked waits until len(streams) < maxConcurrentStreams.
|
||||||
// Must hold cc.mu.
|
// Must hold cc.mu.
|
||||||
func (cc *ClientConn) awaitOpenSlotForStreamLocked(cs *clientStream) error {
|
func (cc *ClientConn) awaitOpenSlotForStreamLocked(cs *clientStream) error {
|
||||||
for {
|
for {
|
||||||
|
|||||||
2
vendor/golang.org/x/net/trace/histogram.go
generated
vendored
2
vendor/golang.org/x/net/trace/histogram.go
generated
vendored
@ -32,7 +32,7 @@ type histogram struct {
|
|||||||
valueCount int64 // number of values recorded for single value
|
valueCount int64 // number of values recorded for single value
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddMeasurement records a value measurement observation to the histogram.
|
// addMeasurement records a value measurement observation to the histogram.
|
||||||
func (h *histogram) addMeasurement(value int64) {
|
func (h *histogram) addMeasurement(value int64) {
|
||||||
// TODO: assert invariant
|
// TODO: assert invariant
|
||||||
h.sum += value
|
h.sum += value
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c
generated
vendored
1
vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c
generated
vendored
@ -2,6 +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 (386 || amd64 || amd64p32) && gccgo
|
||||||
// +build 386 amd64 amd64p32
|
// +build 386 amd64 amd64p32
|
||||||
// +build gccgo
|
// +build gccgo
|
||||||
|
|
||||||
|
|||||||
11
vendor/golang.org/x/sys/cpu/endian_big.go
generated
vendored
Normal file
11
vendor/golang.org/x/sys/cpu/endian_big.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// Copyright 2023 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 armbe || arm64be || m68k || mips || mips64 || mips64p32 || ppc || ppc64 || s390 || s390x || shbe || sparc || sparc64
|
||||||
|
// +build armbe arm64be m68k mips mips64 mips64p32 ppc ppc64 s390 s390x shbe sparc sparc64
|
||||||
|
|
||||||
|
package cpu
|
||||||
|
|
||||||
|
// IsBigEndian records whether the GOARCH's byte order is big endian.
|
||||||
|
const IsBigEndian = true
|
||||||
11
vendor/golang.org/x/sys/cpu/endian_little.go
generated
vendored
Normal file
11
vendor/golang.org/x/sys/cpu/endian_little.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// Copyright 2023 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 386 || amd64 || amd64p32 || alpha || arm || arm64 || loong64 || mipsle || mips64le || mips64p32le || nios2 || ppc64le || riscv || riscv64 || sh
|
||||||
|
// +build 386 amd64 amd64p32 alpha arm arm64 loong64 mipsle mips64le mips64p32le nios2 ppc64le riscv riscv64 sh
|
||||||
|
|
||||||
|
package cpu
|
||||||
|
|
||||||
|
// IsBigEndian records whether the GOARCH's byte order is big endian.
|
||||||
|
const IsBigEndian = false
|
||||||
4
vendor/golang.org/x/sys/unix/gccgo_c.c
generated
vendored
4
vendor/golang.org/x/sys/unix/gccgo_c.c
generated
vendored
@ -2,8 +2,8 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
// +build gccgo,!hurd
|
//go:build gccgo && !aix && !hurd
|
||||||
// +build !aix,!hurd
|
// +build gccgo,!aix,!hurd
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/syscall_darwin.go
generated
vendored
1
vendor/golang.org/x/sys/unix/syscall_darwin.go
generated
vendored
@ -230,6 +230,7 @@ func direntNamlen(buf []byte) (uint64, bool) {
|
|||||||
|
|
||||||
func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) }
|
func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) }
|
||||||
func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) }
|
func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) }
|
||||||
|
func PtraceDenyAttach() (err error) { return ptrace(PT_DENY_ATTACH, 0, 0, 0) }
|
||||||
|
|
||||||
//sysnb pipe(p *[2]int32) (err error)
|
//sysnb pipe(p *[2]int32) (err error)
|
||||||
|
|
||||||
|
|||||||
9
vendor/golang.org/x/sys/unix/syscall_freebsd_386.go
generated
vendored
9
vendor/golang.org/x/sys/unix/syscall_freebsd_386.go
generated
vendored
@ -60,8 +60,13 @@ func PtraceGetFsBase(pid int, fsbase *int64) (err error) {
|
|||||||
return ptrace(PT_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
|
return ptrace(PT_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
func PtraceIO(req int, pid int, offs uintptr, out []byte, countin int) (count int, err error) {
|
||||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: uintptr(unsafe.Pointer(addr)), Addr: uintptr(unsafe.Pointer(&out[0])), Len: uint32(countin)}
|
ioDesc := PtraceIoDesc{
|
||||||
|
Op: int32(req),
|
||||||
|
Offs: offs,
|
||||||
|
Addr: uintptr(unsafe.Pointer(&out[0])), // TODO(#58351): this is not safe.
|
||||||
|
Len: uint32(countin),
|
||||||
|
}
|
||||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||||
return int(ioDesc.Len), err
|
return int(ioDesc.Len), err
|
||||||
}
|
}
|
||||||
|
|||||||
9
vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go
generated
vendored
9
vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go
generated
vendored
@ -60,8 +60,13 @@ func PtraceGetFsBase(pid int, fsbase *int64) (err error) {
|
|||||||
return ptrace(PT_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
|
return ptrace(PT_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
func PtraceIO(req int, pid int, offs uintptr, out []byte, countin int) (count int, err error) {
|
||||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: uintptr(unsafe.Pointer(addr)), Addr: uintptr(unsafe.Pointer(&out[0])), Len: uint64(countin)}
|
ioDesc := PtraceIoDesc{
|
||||||
|
Op: int32(req),
|
||||||
|
Offs: offs,
|
||||||
|
Addr: uintptr(unsafe.Pointer(&out[0])), // TODO(#58351): this is not safe.
|
||||||
|
Len: uint64(countin),
|
||||||
|
}
|
||||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||||
return int(ioDesc.Len), err
|
return int(ioDesc.Len), err
|
||||||
}
|
}
|
||||||
|
|||||||
9
vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go
generated
vendored
9
vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go
generated
vendored
@ -56,8 +56,13 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
|||||||
|
|
||||||
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||||
|
|
||||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
func PtraceIO(req int, pid int, offs uintptr, out []byte, countin int) (count int, err error) {
|
||||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: uintptr(unsafe.Pointer(addr)), Addr: uintptr(unsafe.Pointer(&out[0])), Len: uint32(countin)}
|
ioDesc := PtraceIoDesc{
|
||||||
|
Op: int32(req),
|
||||||
|
Offs: offs,
|
||||||
|
Addr: uintptr(unsafe.Pointer(&out[0])), // TODO(#58351): this is not safe.
|
||||||
|
Len: uint32(countin),
|
||||||
|
}
|
||||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||||
return int(ioDesc.Len), err
|
return int(ioDesc.Len), err
|
||||||
}
|
}
|
||||||
|
|||||||
9
vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go
generated
vendored
9
vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go
generated
vendored
@ -56,8 +56,13 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
|||||||
|
|
||||||
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||||
|
|
||||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
func PtraceIO(req int, pid int, offs uintptr, out []byte, countin int) (count int, err error) {
|
||||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: uintptr(unsafe.Pointer(addr)), Addr: uintptr(unsafe.Pointer(&out[0])), Len: uint64(countin)}
|
ioDesc := PtraceIoDesc{
|
||||||
|
Op: int32(req),
|
||||||
|
Offs: offs,
|
||||||
|
Addr: uintptr(unsafe.Pointer(&out[0])), // TODO(#58351): this is not safe.
|
||||||
|
Len: uint64(countin),
|
||||||
|
}
|
||||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||||
return int(ioDesc.Len), err
|
return int(ioDesc.Len), err
|
||||||
}
|
}
|
||||||
|
|||||||
9
vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go
generated
vendored
9
vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go
generated
vendored
@ -56,8 +56,13 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
|||||||
|
|
||||||
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||||
|
|
||||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
func PtraceIO(req int, pid int, offs uintptr, out []byte, countin int) (count int, err error) {
|
||||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: uintptr(unsafe.Pointer(addr)), Addr: uintptr(unsafe.Pointer(&out[0])), Len: uint64(countin)}
|
ioDesc := PtraceIoDesc{
|
||||||
|
Op: int32(req),
|
||||||
|
Offs: offs,
|
||||||
|
Addr: uintptr(unsafe.Pointer(&out[0])), // TODO(#58351): this is not safe.
|
||||||
|
Len: uint64(countin),
|
||||||
|
}
|
||||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||||
return int(ioDesc.Len), err
|
return int(ioDesc.Len), err
|
||||||
}
|
}
|
||||||
|
|||||||
3
vendor/golang.org/x/sys/unix/syscall_linux.go
generated
vendored
3
vendor/golang.org/x/sys/unix/syscall_linux.go
generated
vendored
@ -1800,6 +1800,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
|||||||
//sysnb Capset(hdr *CapUserHeader, data *CapUserData) (err error)
|
//sysnb Capset(hdr *CapUserHeader, data *CapUserData) (err error)
|
||||||
//sys Chdir(path string) (err error)
|
//sys Chdir(path string) (err error)
|
||||||
//sys Chroot(path string) (err error)
|
//sys Chroot(path string) (err error)
|
||||||
|
//sys ClockAdjtime(clockid int32, buf *Timex) (state int, err error)
|
||||||
//sys ClockGetres(clockid int32, res *Timespec) (err error)
|
//sys ClockGetres(clockid int32, res *Timespec) (err error)
|
||||||
//sys ClockGettime(clockid int32, time *Timespec) (err error)
|
//sys ClockGettime(clockid int32, time *Timespec) (err error)
|
||||||
//sys ClockNanosleep(clockid int32, flags int, request *Timespec, remain *Timespec) (err error)
|
//sys ClockNanosleep(clockid int32, flags int, request *Timespec, remain *Timespec) (err error)
|
||||||
@ -1999,7 +2000,7 @@ func appendBytes(vecs []Iovec, bs [][]byte) []Iovec {
|
|||||||
// offs2lohi splits offs into its low and high order bits.
|
// offs2lohi splits offs into its low and high order bits.
|
||||||
func offs2lohi(offs int64) (lo, hi uintptr) {
|
func offs2lohi(offs int64) (lo, hi uintptr) {
|
||||||
const longBits = SizeofLong * 8
|
const longBits = SizeofLong * 8
|
||||||
return uintptr(offs), uintptr(uint64(offs) >> longBits)
|
return uintptr(offs), uintptr(uint64(offs) >> (longBits - 1) >> 1) // two shifts to avoid false positive in vet
|
||||||
}
|
}
|
||||||
|
|
||||||
func Readv(fd int, iovs [][]byte) (n int, err error) {
|
func Readv(fd int, iovs [][]byte) (n int, err error) {
|
||||||
|
|||||||
2
vendor/golang.org/x/sys/unix/syscall_unix.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_unix.go
generated
vendored
@ -578,7 +578,7 @@ func Lutimes(path string, tv []Timeval) error {
|
|||||||
return UtimesNanoAt(AT_FDCWD, path, ts, AT_SYMLINK_NOFOLLOW)
|
return UtimesNanoAt(AT_FDCWD, path, ts, AT_SYMLINK_NOFOLLOW)
|
||||||
}
|
}
|
||||||
|
|
||||||
// emptyIovec reports whether there are no bytes in the slice of Iovec.
|
// emptyIovecs reports whether there are no bytes in the slice of Iovec.
|
||||||
func emptyIovecs(iov []Iovec) bool {
|
func emptyIovecs(iov []Iovec) bool {
|
||||||
for i := range iov {
|
for i := range iov {
|
||||||
if iov[i].Len > 0 {
|
if iov[i].Len > 0 {
|
||||||
|
|||||||
2
vendor/golang.org/x/sys/unix/timestruct.go
generated
vendored
2
vendor/golang.org/x/sys/unix/timestruct.go
generated
vendored
@ -9,7 +9,7 @@ package unix
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
// TimespecToNSec returns the time stored in ts as nanoseconds.
|
// TimespecToNsec returns the time stored in ts as nanoseconds.
|
||||||
func TimespecToNsec(ts Timespec) int64 { return ts.Nano() }
|
func TimespecToNsec(ts Timespec) int64 { return ts.Nano() }
|
||||||
|
|
||||||
// NsecToTimespec converts a number of nanoseconds into a Timespec.
|
// NsecToTimespec converts a number of nanoseconds into a Timespec.
|
||||||
|
|||||||
9
vendor/golang.org/x/sys/unix/xattr_bsd.go
generated
vendored
9
vendor/golang.org/x/sys/unix/xattr_bsd.go
generated
vendored
@ -36,9 +36,14 @@ func xattrnamespace(fullattr string) (ns int, attr string, err error) {
|
|||||||
func initxattrdest(dest []byte, idx int) (d unsafe.Pointer) {
|
func initxattrdest(dest []byte, idx int) (d unsafe.Pointer) {
|
||||||
if len(dest) > idx {
|
if len(dest) > idx {
|
||||||
return unsafe.Pointer(&dest[idx])
|
return unsafe.Pointer(&dest[idx])
|
||||||
} else {
|
|
||||||
return unsafe.Pointer(_zero)
|
|
||||||
}
|
}
|
||||||
|
if dest != nil {
|
||||||
|
// extattr_get_file and extattr_list_file treat NULL differently from
|
||||||
|
// a non-NULL pointer of length zero. Preserve the property of nilness,
|
||||||
|
// even if we can't use dest directly.
|
||||||
|
return unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FreeBSD and NetBSD implement their own syscalls to handle extended attributes
|
// FreeBSD and NetBSD implement their own syscalls to handle extended attributes
|
||||||
|
|||||||
30
vendor/golang.org/x/sys/unix/zerrors_linux.go
generated
vendored
30
vendor/golang.org/x/sys/unix/zerrors_linux.go
generated
vendored
@ -457,7 +457,6 @@ const (
|
|||||||
B600 = 0x8
|
B600 = 0x8
|
||||||
B75 = 0x2
|
B75 = 0x2
|
||||||
B9600 = 0xd
|
B9600 = 0xd
|
||||||
BALLOON_KVM_MAGIC = 0x13661366
|
|
||||||
BDEVFS_MAGIC = 0x62646576
|
BDEVFS_MAGIC = 0x62646576
|
||||||
BINDERFS_SUPER_MAGIC = 0x6c6f6f70
|
BINDERFS_SUPER_MAGIC = 0x6c6f6f70
|
||||||
BINFMTFS_MAGIC = 0x42494e4d
|
BINFMTFS_MAGIC = 0x42494e4d
|
||||||
@ -563,6 +562,7 @@ const (
|
|||||||
BUS_USB = 0x3
|
BUS_USB = 0x3
|
||||||
BUS_VIRTUAL = 0x6
|
BUS_VIRTUAL = 0x6
|
||||||
CAN_BCM = 0x2
|
CAN_BCM = 0x2
|
||||||
|
CAN_BUS_OFF_THRESHOLD = 0x100
|
||||||
CAN_CTRLMODE_3_SAMPLES = 0x4
|
CAN_CTRLMODE_3_SAMPLES = 0x4
|
||||||
CAN_CTRLMODE_BERR_REPORTING = 0x10
|
CAN_CTRLMODE_BERR_REPORTING = 0x10
|
||||||
CAN_CTRLMODE_CC_LEN8_DLC = 0x100
|
CAN_CTRLMODE_CC_LEN8_DLC = 0x100
|
||||||
@ -577,9 +577,12 @@ const (
|
|||||||
CAN_EFF_FLAG = 0x80000000
|
CAN_EFF_FLAG = 0x80000000
|
||||||
CAN_EFF_ID_BITS = 0x1d
|
CAN_EFF_ID_BITS = 0x1d
|
||||||
CAN_EFF_MASK = 0x1fffffff
|
CAN_EFF_MASK = 0x1fffffff
|
||||||
|
CAN_ERROR_PASSIVE_THRESHOLD = 0x80
|
||||||
|
CAN_ERROR_WARNING_THRESHOLD = 0x60
|
||||||
CAN_ERR_ACK = 0x20
|
CAN_ERR_ACK = 0x20
|
||||||
CAN_ERR_BUSERROR = 0x80
|
CAN_ERR_BUSERROR = 0x80
|
||||||
CAN_ERR_BUSOFF = 0x40
|
CAN_ERR_BUSOFF = 0x40
|
||||||
|
CAN_ERR_CNT = 0x200
|
||||||
CAN_ERR_CRTL = 0x4
|
CAN_ERR_CRTL = 0x4
|
||||||
CAN_ERR_CRTL_ACTIVE = 0x40
|
CAN_ERR_CRTL_ACTIVE = 0x40
|
||||||
CAN_ERR_CRTL_RX_OVERFLOW = 0x1
|
CAN_ERR_CRTL_RX_OVERFLOW = 0x1
|
||||||
@ -820,9 +823,9 @@ const (
|
|||||||
DM_UUID_FLAG = 0x4000
|
DM_UUID_FLAG = 0x4000
|
||||||
DM_UUID_LEN = 0x81
|
DM_UUID_LEN = 0x81
|
||||||
DM_VERSION = 0xc138fd00
|
DM_VERSION = 0xc138fd00
|
||||||
DM_VERSION_EXTRA = "-ioctl (2022-02-22)"
|
DM_VERSION_EXTRA = "-ioctl (2022-07-28)"
|
||||||
DM_VERSION_MAJOR = 0x4
|
DM_VERSION_MAJOR = 0x4
|
||||||
DM_VERSION_MINOR = 0x2e
|
DM_VERSION_MINOR = 0x2f
|
||||||
DM_VERSION_PATCHLEVEL = 0x0
|
DM_VERSION_PATCHLEVEL = 0x0
|
||||||
DT_BLK = 0x6
|
DT_BLK = 0x6
|
||||||
DT_CHR = 0x2
|
DT_CHR = 0x2
|
||||||
@ -1049,6 +1052,7 @@ const (
|
|||||||
ETH_P_CAIF = 0xf7
|
ETH_P_CAIF = 0xf7
|
||||||
ETH_P_CAN = 0xc
|
ETH_P_CAN = 0xc
|
||||||
ETH_P_CANFD = 0xd
|
ETH_P_CANFD = 0xd
|
||||||
|
ETH_P_CANXL = 0xe
|
||||||
ETH_P_CFM = 0x8902
|
ETH_P_CFM = 0x8902
|
||||||
ETH_P_CONTROL = 0x16
|
ETH_P_CONTROL = 0x16
|
||||||
ETH_P_CUST = 0x6006
|
ETH_P_CUST = 0x6006
|
||||||
@ -1060,6 +1064,7 @@ const (
|
|||||||
ETH_P_DNA_RT = 0x6003
|
ETH_P_DNA_RT = 0x6003
|
||||||
ETH_P_DSA = 0x1b
|
ETH_P_DSA = 0x1b
|
||||||
ETH_P_DSA_8021Q = 0xdadb
|
ETH_P_DSA_8021Q = 0xdadb
|
||||||
|
ETH_P_DSA_A5PSW = 0xe001
|
||||||
ETH_P_ECONET = 0x18
|
ETH_P_ECONET = 0x18
|
||||||
ETH_P_EDSA = 0xdada
|
ETH_P_EDSA = 0xdada
|
||||||
ETH_P_ERSPAN = 0x88be
|
ETH_P_ERSPAN = 0x88be
|
||||||
@ -1194,8 +1199,10 @@ const (
|
|||||||
FAN_MARK_EVICTABLE = 0x200
|
FAN_MARK_EVICTABLE = 0x200
|
||||||
FAN_MARK_FILESYSTEM = 0x100
|
FAN_MARK_FILESYSTEM = 0x100
|
||||||
FAN_MARK_FLUSH = 0x80
|
FAN_MARK_FLUSH = 0x80
|
||||||
|
FAN_MARK_IGNORE = 0x400
|
||||||
FAN_MARK_IGNORED_MASK = 0x20
|
FAN_MARK_IGNORED_MASK = 0x20
|
||||||
FAN_MARK_IGNORED_SURV_MODIFY = 0x40
|
FAN_MARK_IGNORED_SURV_MODIFY = 0x40
|
||||||
|
FAN_MARK_IGNORE_SURV = 0x440
|
||||||
FAN_MARK_INODE = 0x0
|
FAN_MARK_INODE = 0x0
|
||||||
FAN_MARK_MOUNT = 0x10
|
FAN_MARK_MOUNT = 0x10
|
||||||
FAN_MARK_ONLYDIR = 0x8
|
FAN_MARK_ONLYDIR = 0x8
|
||||||
@ -1253,6 +1260,7 @@ const (
|
|||||||
FSCRYPT_MODE_AES_128_CBC = 0x5
|
FSCRYPT_MODE_AES_128_CBC = 0x5
|
||||||
FSCRYPT_MODE_AES_128_CTS = 0x6
|
FSCRYPT_MODE_AES_128_CTS = 0x6
|
||||||
FSCRYPT_MODE_AES_256_CTS = 0x4
|
FSCRYPT_MODE_AES_256_CTS = 0x4
|
||||||
|
FSCRYPT_MODE_AES_256_HCTR2 = 0xa
|
||||||
FSCRYPT_MODE_AES_256_XTS = 0x1
|
FSCRYPT_MODE_AES_256_XTS = 0x1
|
||||||
FSCRYPT_POLICY_FLAGS_PAD_16 = 0x2
|
FSCRYPT_POLICY_FLAGS_PAD_16 = 0x2
|
||||||
FSCRYPT_POLICY_FLAGS_PAD_32 = 0x3
|
FSCRYPT_POLICY_FLAGS_PAD_32 = 0x3
|
||||||
@ -1430,6 +1438,7 @@ const (
|
|||||||
IFF_NOARP = 0x80
|
IFF_NOARP = 0x80
|
||||||
IFF_NOFILTER = 0x1000
|
IFF_NOFILTER = 0x1000
|
||||||
IFF_NOTRAILERS = 0x20
|
IFF_NOTRAILERS = 0x20
|
||||||
|
IFF_NO_CARRIER = 0x40
|
||||||
IFF_NO_PI = 0x1000
|
IFF_NO_PI = 0x1000
|
||||||
IFF_ONE_QUEUE = 0x2000
|
IFF_ONE_QUEUE = 0x2000
|
||||||
IFF_PERSIST = 0x800
|
IFF_PERSIST = 0x800
|
||||||
@ -1805,6 +1814,7 @@ const (
|
|||||||
MADV_DONTDUMP = 0x10
|
MADV_DONTDUMP = 0x10
|
||||||
MADV_DONTFORK = 0xa
|
MADV_DONTFORK = 0xa
|
||||||
MADV_DONTNEED = 0x4
|
MADV_DONTNEED = 0x4
|
||||||
|
MADV_DONTNEED_LOCKED = 0x18
|
||||||
MADV_FREE = 0x8
|
MADV_FREE = 0x8
|
||||||
MADV_HUGEPAGE = 0xe
|
MADV_HUGEPAGE = 0xe
|
||||||
MADV_HWPOISON = 0x64
|
MADV_HWPOISON = 0x64
|
||||||
@ -1846,7 +1856,7 @@ const (
|
|||||||
MFD_ALLOW_SEALING = 0x2
|
MFD_ALLOW_SEALING = 0x2
|
||||||
MFD_CLOEXEC = 0x1
|
MFD_CLOEXEC = 0x1
|
||||||
MFD_HUGETLB = 0x4
|
MFD_HUGETLB = 0x4
|
||||||
MFD_HUGE_16GB = -0x78000000
|
MFD_HUGE_16GB = 0x88000000
|
||||||
MFD_HUGE_16MB = 0x60000000
|
MFD_HUGE_16MB = 0x60000000
|
||||||
MFD_HUGE_1GB = 0x78000000
|
MFD_HUGE_1GB = 0x78000000
|
||||||
MFD_HUGE_1MB = 0x50000000
|
MFD_HUGE_1MB = 0x50000000
|
||||||
@ -2212,6 +2222,11 @@ const (
|
|||||||
PERF_AUX_FLAG_PARTIAL = 0x4
|
PERF_AUX_FLAG_PARTIAL = 0x4
|
||||||
PERF_AUX_FLAG_PMU_FORMAT_TYPE_MASK = 0xff00
|
PERF_AUX_FLAG_PMU_FORMAT_TYPE_MASK = 0xff00
|
||||||
PERF_AUX_FLAG_TRUNCATED = 0x1
|
PERF_AUX_FLAG_TRUNCATED = 0x1
|
||||||
|
PERF_BR_ARM64_DEBUG_DATA = 0x7
|
||||||
|
PERF_BR_ARM64_DEBUG_EXIT = 0x5
|
||||||
|
PERF_BR_ARM64_DEBUG_HALT = 0x4
|
||||||
|
PERF_BR_ARM64_DEBUG_INST = 0x6
|
||||||
|
PERF_BR_ARM64_FIQ = 0x3
|
||||||
PERF_FLAG_FD_CLOEXEC = 0x8
|
PERF_FLAG_FD_CLOEXEC = 0x8
|
||||||
PERF_FLAG_FD_NO_GROUP = 0x1
|
PERF_FLAG_FD_NO_GROUP = 0x1
|
||||||
PERF_FLAG_FD_OUTPUT = 0x2
|
PERF_FLAG_FD_OUTPUT = 0x2
|
||||||
@ -2232,6 +2247,8 @@ const (
|
|||||||
PERF_MEM_LOCK_NA = 0x1
|
PERF_MEM_LOCK_NA = 0x1
|
||||||
PERF_MEM_LOCK_SHIFT = 0x18
|
PERF_MEM_LOCK_SHIFT = 0x18
|
||||||
PERF_MEM_LVLNUM_ANY_CACHE = 0xb
|
PERF_MEM_LVLNUM_ANY_CACHE = 0xb
|
||||||
|
PERF_MEM_LVLNUM_CXL = 0x9
|
||||||
|
PERF_MEM_LVLNUM_IO = 0xa
|
||||||
PERF_MEM_LVLNUM_L1 = 0x1
|
PERF_MEM_LVLNUM_L1 = 0x1
|
||||||
PERF_MEM_LVLNUM_L2 = 0x2
|
PERF_MEM_LVLNUM_L2 = 0x2
|
||||||
PERF_MEM_LVLNUM_L3 = 0x3
|
PERF_MEM_LVLNUM_L3 = 0x3
|
||||||
@ -2265,6 +2282,7 @@ const (
|
|||||||
PERF_MEM_REMOTE_REMOTE = 0x1
|
PERF_MEM_REMOTE_REMOTE = 0x1
|
||||||
PERF_MEM_REMOTE_SHIFT = 0x25
|
PERF_MEM_REMOTE_SHIFT = 0x25
|
||||||
PERF_MEM_SNOOPX_FWD = 0x1
|
PERF_MEM_SNOOPX_FWD = 0x1
|
||||||
|
PERF_MEM_SNOOPX_PEER = 0x2
|
||||||
PERF_MEM_SNOOPX_SHIFT = 0x26
|
PERF_MEM_SNOOPX_SHIFT = 0x26
|
||||||
PERF_MEM_SNOOP_HIT = 0x4
|
PERF_MEM_SNOOP_HIT = 0x4
|
||||||
PERF_MEM_SNOOP_HITM = 0x10
|
PERF_MEM_SNOOP_HITM = 0x10
|
||||||
@ -2301,7 +2319,6 @@ const (
|
|||||||
PERF_SAMPLE_BRANCH_PLM_ALL = 0x7
|
PERF_SAMPLE_BRANCH_PLM_ALL = 0x7
|
||||||
PERF_SAMPLE_WEIGHT_TYPE = 0x1004000
|
PERF_SAMPLE_WEIGHT_TYPE = 0x1004000
|
||||||
PIPEFS_MAGIC = 0x50495045
|
PIPEFS_MAGIC = 0x50495045
|
||||||
PPC_CMM_MAGIC = 0xc7571590
|
|
||||||
PPPIOCGNPMODE = 0xc008744c
|
PPPIOCGNPMODE = 0xc008744c
|
||||||
PPPIOCNEWUNIT = 0xc004743e
|
PPPIOCNEWUNIT = 0xc004743e
|
||||||
PRIO_PGRP = 0x1
|
PRIO_PGRP = 0x1
|
||||||
@ -2999,6 +3016,7 @@ const (
|
|||||||
STATX_BLOCKS = 0x400
|
STATX_BLOCKS = 0x400
|
||||||
STATX_BTIME = 0x800
|
STATX_BTIME = 0x800
|
||||||
STATX_CTIME = 0x80
|
STATX_CTIME = 0x80
|
||||||
|
STATX_DIOALIGN = 0x2000
|
||||||
STATX_GID = 0x10
|
STATX_GID = 0x10
|
||||||
STATX_INO = 0x100
|
STATX_INO = 0x100
|
||||||
STATX_MNT_ID = 0x1000
|
STATX_MNT_ID = 0x1000
|
||||||
@ -3392,9 +3410,7 @@ const (
|
|||||||
XDP_ZEROCOPY = 0x4
|
XDP_ZEROCOPY = 0x4
|
||||||
XENFS_SUPER_MAGIC = 0xabba1974
|
XENFS_SUPER_MAGIC = 0xabba1974
|
||||||
XFS_SUPER_MAGIC = 0x58465342
|
XFS_SUPER_MAGIC = 0x58465342
|
||||||
Z3FOLD_MAGIC = 0x33
|
|
||||||
ZONEFS_MAGIC = 0x5a4f4653
|
ZONEFS_MAGIC = 0x5a4f4653
|
||||||
ZSMALLOC_MAGIC = 0x58295829
|
|
||||||
_HIDIOCGRAWNAME_LEN = 0x80
|
_HIDIOCGRAWNAME_LEN = 0x80
|
||||||
_HIDIOCGRAWPHYS_LEN = 0x40
|
_HIDIOCGRAWPHYS_LEN = 0x40
|
||||||
_HIDIOCGRAWUNIQ_LEN = 0x40
|
_HIDIOCGRAWUNIQ_LEN = 0x40
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/zerrors_linux_386.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_386.go
generated
vendored
@ -133,6 +133,7 @@ const (
|
|||||||
MEMGETREGIONCOUNT = 0x80044d07
|
MEMGETREGIONCOUNT = 0x80044d07
|
||||||
MEMISLOCKED = 0x80084d17
|
MEMISLOCKED = 0x80084d17
|
||||||
MEMLOCK = 0x40084d05
|
MEMLOCK = 0x40084d05
|
||||||
|
MEMREAD = 0xc03c4d1a
|
||||||
MEMREADOOB = 0xc00c4d04
|
MEMREADOOB = 0xc00c4d04
|
||||||
MEMSETBADBLOCK = 0x40084d0c
|
MEMSETBADBLOCK = 0x40084d0c
|
||||||
MEMUNLOCK = 0x40084d06
|
MEMUNLOCK = 0x40084d06
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
generated
vendored
@ -133,6 +133,7 @@ const (
|
|||||||
MEMGETREGIONCOUNT = 0x80044d07
|
MEMGETREGIONCOUNT = 0x80044d07
|
||||||
MEMISLOCKED = 0x80084d17
|
MEMISLOCKED = 0x80084d17
|
||||||
MEMLOCK = 0x40084d05
|
MEMLOCK = 0x40084d05
|
||||||
|
MEMREAD = 0xc0404d1a
|
||||||
MEMREADOOB = 0xc0104d04
|
MEMREADOOB = 0xc0104d04
|
||||||
MEMSETBADBLOCK = 0x40084d0c
|
MEMSETBADBLOCK = 0x40084d0c
|
||||||
MEMUNLOCK = 0x40084d06
|
MEMUNLOCK = 0x40084d06
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
generated
vendored
@ -131,6 +131,7 @@ const (
|
|||||||
MEMGETREGIONCOUNT = 0x80044d07
|
MEMGETREGIONCOUNT = 0x80044d07
|
||||||
MEMISLOCKED = 0x80084d17
|
MEMISLOCKED = 0x80084d17
|
||||||
MEMLOCK = 0x40084d05
|
MEMLOCK = 0x40084d05
|
||||||
|
MEMREAD = 0xc0404d1a
|
||||||
MEMREADOOB = 0xc00c4d04
|
MEMREADOOB = 0xc00c4d04
|
||||||
MEMSETBADBLOCK = 0x40084d0c
|
MEMSETBADBLOCK = 0x40084d0c
|
||||||
MEMUNLOCK = 0x40084d06
|
MEMUNLOCK = 0x40084d06
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user