Updated dependencies and added avct/uasurfer (#8089)

* Updated dependencies and added avct/uasurfer

* Added uasurfer to NOTICE.txt
Этот коммит содержится в:
Harrison Healey
2018-01-16 12:03:31 -05:00
коммит произвёл GitHub
родитель f5c8a71698
Коммит 2fa7c464f0
1402 изменённых файлов: 325689 добавлений и 34274 удалений

Просмотреть файл

@@ -2933,3 +2933,207 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---
## uasurfer
This product contains a modified portion of `uasurfer`, a Golang library for parsing User-Agent strings.
* HOMEPAGE
* https://github.com/avct/uasurfer
* LICENSE
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Copyright 2015 Avocet Systems Ltd.
http://avocet.io/opensource
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
Copyright 2015 Avocet Systems Ltd.
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.

68
glide.lock сгенерированный
Просмотреть файл

@@ -5,7 +5,9 @@ imports:
version: 3fbce08846379ec7f4f6bc7fce6dd01ce28fae4c
repo: https://github.com/mattermost/log4go.git
- name: github.com/armon/go-metrics
version: 9a4b6e10bed6220a1665955aa2b75afc91eb10b3
version: 7aa49fde808223f8dadfdbfd3a20ff6c19e5f9ec
- name: github.com/avct/uasurfer
version: 7b6f7205267b5b81d20da3f09ec3dea3b3d90cf8
- name: github.com/beorn7/perks
version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
subpackages:
@@ -19,7 +21,7 @@ imports:
subpackages:
- spew
- name: github.com/dgryski/dgoogauth
version: 96977cbd42e27be71f9f731db6634123de7e861a
version: fd153d5969d30bd701e10f3530228f001213047c
- name: github.com/dimchansky/utfbom
version: 6c6132ff69f0f6c088739067407b5d32c52e1d0f
- name: github.com/disintegration/imaging
@@ -31,7 +33,7 @@ imports:
- name: github.com/fsnotify/fsnotify
version: 629574ca2a5df945712d3079857300b5e4da0236
- name: github.com/go-ini/ini
version: f280b3ba517bf5fc98922624f21fb0e7a92adaec
version: 32e4c1e6bc4e7d0d8451aa6b75200d19e37a536a
- name: github.com/go-ldap/ldap
version: 8168ee085ee43257585e50c6441aadf54ecb2c9f
- name: github.com/go-redis/redis
@@ -50,7 +52,7 @@ imports:
- raster
- truetype
- name: github.com/golang/protobuf
version: 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9
version: 1e59b77b52bf8e4b449a57e6f79f21226d571845
subpackages:
- proto
- name: github.com/gorilla/context
@@ -70,7 +72,7 @@ imports:
subpackages:
- codec
- name: github.com/hashicorp/go-multierror
version: 83588e72410abfbe4df460eeb6f30841ae47d4c4
version: b7773ae218740a7be65057fc60b366a49b538a44
- name: github.com/hashicorp/go-sockaddr
version: 9b4c5fa5b10a683339a270d664474b9f4aee62fc
- name: github.com/hashicorp/golang-lru
@@ -82,6 +84,7 @@ imports:
subpackages:
- hcl/ast
- hcl/parser
- hcl/printer
- hcl/scanner
- hcl/strconv
- hcl/token
@@ -89,15 +92,19 @@ imports:
- json/scanner
- json/token
- name: github.com/hashicorp/memberlist
<<<<<<< HEAD
version: caa5d20d6a642b7543b3745e54031a96008bee57
- name: github.com/icrowley/fake
version: e64cc2cf92049a299f359734c6ea76073f2a8b2c
=======
version: 3d8438da9589e7b608a83ffac1ef8211486bcb7c
>>>>>>> Updated dependencies and added avct/uasurfer
- name: github.com/inconshreveable/mousetrap
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
- name: github.com/jehiah/go-strftime
version: 834e15c05a45371503440cc195bbd05c9a0968d9
- name: github.com/lib/pq
version: b609790bd85edf8e9ab7e0f8912750a786177bcf
version: 83612a56d3dd153a94a629cd64925371c9adad78
subpackages:
- oid
- name: github.com/magiconair/properties
@@ -117,9 +124,7 @@ imports:
subpackages:
- pbutil
- name: github.com/miekg/dns
version: 9fc4eb252eedf0ef8adc05169ce35da5e31beaba
subpackages:
- internal/socket
version: f5ac34d755eb6975958108413c7802a782ca16c8
- name: github.com/minio/go-homedir
version: 4d76aabb80b22bad8695d3904e943f1fb5e6199f
- name: github.com/minio/minio-go
@@ -134,7 +139,7 @@ imports:
- name: github.com/mitchellh/mapstructure
version: 06020f85339e21b2478f756a78e295255ffa4d6a
- name: github.com/mssola/user_agent
version: a2f39d5a9b15ecc1fa1005b6aae73cd83da240ef
version: 5243daae23628aeae9b6268541406bd5e95d5964
- name: github.com/nicksnyder/go-i18n
version: 0dc1626d56435e9d605a29875701721c54bc9bbd
subpackages:
@@ -143,13 +148,13 @@ imports:
- i18n/language
- i18n/translation
- name: github.com/NYTimes/gziphandler
version: 843330b8a375e6460183b08e030190b1a1eaea13
version: 47ca22a0aeea4c9ceddfb935d818d636d934c312
- name: github.com/pborman/uuid
version: e790cca94e6cc75c7064b1332e63811d4aae1a53
- name: github.com/pelletier/go-toml
version: 4e9e0ee19b60b13eb79915933f44d8ed5f268bdd
version: 0131db6d737cfbbfb678f8b7d92e55e27ce46224
- name: github.com/pkg/errors
version: f15c970de5b76fac0b59abb32d62c17cc7bed265
version: e881fd58d78e04cf6d0de1217f8707c8cc2249bc
- name: github.com/pmezard/go-difflib
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
subpackages:
@@ -159,19 +164,19 @@ imports:
subpackages:
- prometheus
- name: github.com/prometheus/client_model
version: 6f3806018612930941127f2a7c6c453ba2c527d2
version: 99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c
subpackages:
- go
- name: github.com/prometheus/common
version: e3fb1a1acd7605367a2b378bc2e2f893c05174b7
version: 89604d197083d4781071d3c65855d24ecfb0a563
subpackages:
- expfmt
- name: github.com/prometheus/procfs
version: a6e9df898b1336106c743392c48ee0b71f5c4efa
version: b15cd069a83443be3154b719d0cc9fe8117f09fb
- name: github.com/rsc/letsencrypt
version: 33926faef6d434b854ea994228f11d0185faa0c1
- name: github.com/rwcarlsen/goexif
version: 709fab3d192d7c62f86043caff1e7e3fb0f42bd8
version: 17202558c8d9c3fd047859f1a5e73fd9ae709187
subpackages:
- exif
- tiff
@@ -182,19 +187,19 @@ imports:
- name: github.com/segmentio/backo-go
version: 204274ad699c0983a70203a566887f17a717fef4
- name: github.com/spf13/afero
version: 5660eeed305fe5f69c8fc6cf899132a459a97064
version: 57afd63c68602b63ed976de00dd066ccb3c319db
subpackages:
- mem
- name: github.com/spf13/cast
version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4
- name: github.com/spf13/cobra
version: 2da4a54c5ceefcee7ca5dd0eea1e18a3b6366489
version: b95ab734e27d33e0d8fbabf71ca990568d4e2020
- name: github.com/spf13/jwalterweatherman
version: 12bd96e66386c1960ab0f74ced1362f66f552f7b
version: 7c0cea34c8ece3fbeb2b27ab9b59511d360fb394
- name: github.com/spf13/pflag
version: e57e3eeb33f795204c1ca35f56c44f83227c6e66
- name: github.com/spf13/viper
version: 4dddf7c62e16bce5807744018f5b753bfe21bbd2
version: aafc9e6bc7b7bb53ddaa75a5ef49a17d6e654be5
- name: github.com/stretchr/objx
version: cbeaeb16a013161a98496fad62933b1d21786672
- name: github.com/stretchr/testify
@@ -207,19 +212,21 @@ imports:
- name: github.com/tylerb/graceful
version: 4654dfbb6ad53cb5e27f37d99b02e16c1872fbbb
- name: github.com/xenolf/lego
version: aa94fb4696349fd6f35168dabe3ab030ddf3e484
version: b929aa5aab5ad2e197bb3d74ef99fac61bfa47bc
subpackages:
- acme
- name: github.com/xtgo/uuid
version: a0b114877d4caeffbd7f87e3757c17fce570fea7
- name: golang.org/x/crypto
version: 6a293f2d4b14b8e6d3f0539e383f6d0d30fce3fd
version: b3c9a1d25cfbbbab0ff4780b71c4f54e6e92a0de
subpackages:
- bcrypt
- blowfish
- ed25519
- ed25519/internal/edwards25519
- ocsp
- name: golang.org/x/image
version: f7e31b4ea2e3413ab91b4e7d2dc83e5f8d19a44c
version: 12117c17ca67ffa1ce22e9409f3b0b0a93ac08c7
subpackages:
- bmp
- font
@@ -227,17 +234,22 @@ imports:
- tiff
- tiff/lzw
- name: golang.org/x/net
version: a337091b0525af65de94df2eb7e98bd9962dcbe2
version: 434ec0c7fe3742c984919a691b2018a6e9694425
subpackages:
- bpf
- context
- html
- html/atom
- internal/iana
- internal/socket
- ipv4
- ipv6
- name: golang.org/x/sys
version: 1e2299c37cc91a509f1b12369872d27be0ce98a6
version: 810d7000345868fc619eb81f46307107118f4ae1
subpackages:
- unix
- name: golang.org/x/text
version: 88f656faf3f37f690df1a32515b479415e1a6769
version: e19ae1496984b1c655b8044a65c0300a3c878dd3
subpackages:
- transform
- unicode/norm
@@ -266,5 +278,5 @@ imports:
subpackages:
- store/memstore
- name: gopkg.in/yaml.v2
version: eb3733d160e74a9c7e442f435eb3bea458e1d19f
version: d670f9405373e636a5a2765eea47fac0c9bc91a4
testImports: []

Просмотреть файл

@@ -95,3 +95,4 @@ import:
version: 2.0.0
- package: github.com/mattermost/html2text
- package: github.com/icrowley/fake
- package: github.com/avct/uasurfer

35
vendor/github.com/NYTimes/gziphandler/gzip.go сгенерированный поставляемый
Просмотреть файл

@@ -82,7 +82,14 @@ type GzipResponseWriter struct {
buf []byte // Holds the first part of the write before reaching the minSize or the end of the write.
contentTypes []string // Only compress if the response is one of these content-types. All are accepted if empty.
flushed bool // Indicate if the stream was already flushed
}
type GzipResponseWriterWithCloseNotify struct {
*GzipResponseWriter
}
func (w *GzipResponseWriterWithCloseNotify) CloseNotify() <-chan bool {
return w.ResponseWriter.(http.CloseNotifier).CloseNotify()
}
// Write appends data to the gzip writer.
@@ -170,8 +177,7 @@ func (w *GzipResponseWriter) init() {
func (w *GzipResponseWriter) Close() error {
if w.gw == nil {
// Gzip not trigged yet, write out regular response.
// WriteHeader only if it wasn't already wrote by a Flush
if !w.flushed && w.code != 0 {
if w.code != 0 {
w.ResponseWriter.WriteHeader(w.code)
}
if w.buf != nil {
@@ -194,16 +200,18 @@ func (w *GzipResponseWriter) Close() error {
// http.ResponseWriter if it is an http.Flusher. This makes GzipResponseWriter
// an http.Flusher.
func (w *GzipResponseWriter) Flush() {
if w.gw != nil {
w.gw.Flush()
if w.gw == nil {
// Only flush once startGzip has been called.
//
// Flush is thus a no-op until the written body
// exceeds minSize.
return
}
w.gw.Flush()
if fw, ok := w.ResponseWriter.(http.Flusher); ok {
if !w.flushed && w.code != 0 {
w.ResponseWriter.WriteHeader(w.code)
}
fw.Flush()
w.flushed = true
}
}
@@ -264,7 +272,6 @@ func GzipHandlerWithOpts(opts ...option) (func(http.Handler) http.Handler, error
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Add(vary, acceptEncoding)
if acceptsGzip(r) {
gw := &GzipResponseWriter{
ResponseWriter: w,
@@ -274,7 +281,13 @@ func GzipHandlerWithOpts(opts ...option) (func(http.Handler) http.Handler, error
}
defer gw.Close()
h.ServeHTTP(gw, r)
if _, ok := w.(http.CloseNotifier); ok {
gwcn := GzipResponseWriterWithCloseNotify{gw}
h.ServeHTTP(gwcn, r)
} else {
h.ServeHTTP(gw, r)
}
} else {
h.ServeHTTP(w, r)
}

49
vendor/github.com/NYTimes/gziphandler/gzip_test.go сгенерированный поставляемый
Просмотреть файл

@@ -306,23 +306,58 @@ func TestStatusCodes(t *testing.T) {
}
}
func TestStatusCodesFlushed(t *testing.T) {
func TestFlushBeforeWrite(t *testing.T) {
b := []byte(testBody)
handler := GzipHandler(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.WriteHeader(http.StatusNotFound)
rw.(http.Flusher).Flush()
rw.Write([]byte("Not found"))
rw.Write(b)
}))
r := httptest.NewRequest(http.MethodGet, "/", nil)
r.Header.Set(acceptEncoding, "gzip")
r.Header.Set("Accept-Encoding", "gzip")
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
result := w.Result()
if result.StatusCode != http.StatusNotFound {
t.Errorf("StatusCode should have been 404 but was %d", result.StatusCode)
}
res := w.Result()
assert.Equal(t, http.StatusNotFound, res.StatusCode)
assert.Equal(t, "gzip", res.Header.Get("Content-Encoding"))
assert.NotEqual(t, b, w.Body.Bytes())
}
func TestImplementCloseNotifier(t *testing.T) {
GzipHandler(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request){
_, ok := rw.(http.CloseNotifier)
assert.True(t, ok, "response writer must implement http.CloseNotifier")
})).ServeHTTP(&mockRWCloseNotify{}, &http.Request{})
}
func TestNotImplementCloseNotifier(t *testing.T) {
GzipHandler(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request){
_, ok := rw.(http.CloseNotifier)
assert.False(t, ok, "response writer must not implement http.CloseNotifier")
})).ServeHTTP(httptest.NewRecorder(), &http.Request{})
}
type mockRWCloseNotify struct{}
func (m *mockRWCloseNotify) CloseNotify() <-chan bool {
panic("implement me")
}
func (m *mockRWCloseNotify) Header() http.Header {
return http.Header{}
}
func (m *mockRWCloseNotify) Write([]byte) (int, error) {
panic("implement me")
}
func (m *mockRWCloseNotify) WriteHeader(int) {
panic("implement me")
}
func TestIgnoreSubsequentWriteHeader(t *testing.T) {
handler := GzipHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(500)

98
vendor/github.com/armon/go-metrics/prometheus/prometheus.go сгенерированный поставляемый
Просмотреть файл

@@ -13,19 +13,91 @@ import (
"github.com/prometheus/client_golang/prometheus"
)
type PrometheusSink struct {
mu sync.Mutex
gauges map[string]prometheus.Gauge
summaries map[string]prometheus.Summary
counters map[string]prometheus.Counter
var (
// DefaultPrometheusOpts is the default set of options used when creating a
// PrometheusSink.
DefaultPrometheusOpts = PrometheusOpts{
Expiration: 60 * time.Second,
}
)
// PrometheusOpts is used to configure the Prometheus Sink
type PrometheusOpts struct {
// Expiration is the duration a metric is valid for, after which it will be
// untracked. If the value is zero, a metric is never expired.
Expiration time.Duration
}
type PrometheusSink struct {
mu sync.Mutex
gauges map[string]prometheus.Gauge
summaries map[string]prometheus.Summary
counters map[string]prometheus.Counter
updates map[string]time.Time
expiration time.Duration
}
// NewPrometheusSink creates a new PrometheusSink using the default options.
func NewPrometheusSink() (*PrometheusSink, error) {
return &PrometheusSink{
gauges: make(map[string]prometheus.Gauge),
summaries: make(map[string]prometheus.Summary),
counters: make(map[string]prometheus.Counter),
}, nil
return NewPrometheusSinkFrom(DefaultPrometheusOpts)
}
// NewPrometheusSinkFrom creates a new PrometheusSink using the passed options.
func NewPrometheusSinkFrom(opts PrometheusOpts) (*PrometheusSink, error) {
sink := &PrometheusSink{
gauges: make(map[string]prometheus.Gauge),
summaries: make(map[string]prometheus.Summary),
counters: make(map[string]prometheus.Counter),
updates: make(map[string]time.Time),
expiration: opts.Expiration,
}
return sink, prometheus.Register(sink)
}
// Describe is needed to meet the Collector interface.
func (p *PrometheusSink) Describe(c chan<- *prometheus.Desc) {
// We must emit some description otherwise an error is returned. This
// description isn't shown to the user!
prometheus.NewGauge(prometheus.GaugeOpts{Name: "Dummy", Help: "Dummy"}).Describe(c)
}
// Collect meets the collection interface and allows us to enforce our expiration
// logic to clean up ephemeral metrics if their value haven't been set for a
// duration exceeding our allowed expiration time.
func (p *PrometheusSink) Collect(c chan<- prometheus.Metric) {
p.mu.Lock()
defer p.mu.Unlock()
expire := p.expiration != 0
now := time.Now()
for k, v := range p.gauges {
last := p.updates[k]
if expire && last.Add(p.expiration).Before(now) {
delete(p.updates, k)
delete(p.gauges, k)
} else {
v.Collect(c)
}
}
for k, v := range p.summaries {
last := p.updates[k]
if expire && last.Add(p.expiration).Before(now) {
delete(p.updates, k)
delete(p.summaries, k)
} else {
v.Collect(c)
}
}
for k, v := range p.counters {
last := p.updates[k]
if expire && last.Add(p.expiration).Before(now) {
delete(p.updates, k)
delete(p.counters, k)
} else {
v.Collect(c)
}
}
}
var forbiddenChars = regexp.MustCompile("[ .=\\-]")
@@ -65,10 +137,10 @@ func (p *PrometheusSink) SetGaugeWithLabels(parts []string, val float32, labels
Help: key,
ConstLabels: prometheusLabels(labels),
})
prometheus.MustRegister(g)
p.gauges[hash] = g
}
g.Set(float64(val))
p.updates[hash] = time.Now()
}
func (p *PrometheusSink) AddSample(parts []string, val float32) {
@@ -87,10 +159,10 @@ func (p *PrometheusSink) AddSampleWithLabels(parts []string, val float32, labels
MaxAge: 10 * time.Second,
ConstLabels: prometheusLabels(labels),
})
prometheus.MustRegister(g)
p.summaries[hash] = g
}
g.Observe(float64(val))
p.updates[hash] = time.Now()
}
// EmitKey is not implemented. Prometheus doesnt offer a type for which an
@@ -114,8 +186,8 @@ func (p *PrometheusSink) IncrCounterWithLabels(parts []string, val float32, labe
Help: key,
ConstLabels: prometheusLabels(labels),
})
prometheus.MustRegister(g)
p.counters[hash] = g
}
g.Add(float64(val))
p.updates[hash] = time.Now()
}

2
vendor/github.com/armon/go-metrics/start.go сгенерированный поставляемый
Просмотреть файл

@@ -11,7 +11,7 @@ import (
// Config is used to configure metrics settings
type Config struct {
ServiceName string // Prefixed with keys to seperate services
ServiceName string // Prefixed with keys to separate services
HostName string // Hostname to use. If not provided and EnableHostname, it will be os.Hostname
EnableHostname bool // Enable prefixing gauge values with hostname
EnableHostnameLabel bool // Enable adding hostname to labels

56
vendor/github.com/avct/uasurfer/.gitignore сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,56 @@
# Compiled bin #
###################
# Compiled source #
###################
*.dll
*.exe
*.o
*.so
# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
# Configuration Files #
#######################
*.cfg
# Logs and databases #
######################
*.log
*.sql
*.sqlite
logs
coverage.html
coverage.out
# Test Files #
#######################
*.test
# OS generated files #
######################
.DS_Store
.DS_Store?
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# go.rice generated files
*.rice-box.go
# Dev Tools #
######################
.vagrant

11
vendor/github.com/avct/uasurfer/.travis.yml сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,11 @@
sudo: false
language: go
go:
- 1.9.x
- 1.8.x
- 1.7.x
script:
- go test

192
vendor/github.com/avct/uasurfer/LICENSE сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,192 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Copyright 2015 Avocet Systems Ltd.
http://avocet.io/opensource
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
Copyright 2015 Avocet Systems Ltd.
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.

169
vendor/github.com/avct/uasurfer/README.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,169 @@
[![Build Status](https://travis-ci.org/avct/uasurfer.svg?branch=master)](https://travis-ci.org/avct/uasurfer) [![GoDoc](https://godoc.org/github.com/avct/uasurfer?status.svg)](https://godoc.org/github.com/avct/uasurfer) [![Go Report Card](https://goreportcard.com/badge/github.com/avct/uasurfer)](https://goreportcard.com/report/github.com/avct/uasurfer)
# uasurfer
![uasurfer-100px](https://cloud.githubusercontent.com/assets/597902/16172506/9debc136-357a-11e6-90fb-c7c46f50dff0.png)
**User Agent Surfer** (uasurfer) is a lightweight Golang package that parses and abstracts [HTTP User-Agent strings](https://en.wikipedia.org/wiki/User_agent) with particular attention to device type.
The following information is returned by uasurfer from a raw HTTP User-Agent string:
| Name | Example | Coverage in 192,792 parses |
|----------------|---------|--------------------------------|
| Browser name | `chrome` | 99.85% |
| Browser version | `53` | 99.17% |
| Platform | `ipad` | 99.97% |
| OS name | `ios` | 99.96% |
| OS version | `10` | 98.81% |
| Device type | `tablet` | 99.98% |
Layout engine, browser language, and other esoteric attributes are not parsed.
Coverage is estimated from a random sample of real UA strings collected across thousands of sources in US and EU mid-2016.
## Usage
### Parse(ua string) Function
The `Parse()` function accepts a user agent `string` and returns UserAgent struct with named constants and integers for versions (minor, major and patch separately), and the full UA string that was parsed (lowercase). A string can be retrieved by adding `.String()` to a variable, such as `uasurfer.BrowserName.String()`.
```
// Define a user agent string
myUA := "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36"
// Parse() returns all attributes, including returning the full UA string last
ua, uaString := uasurfer.Parse(myUA)
```
where example UserAgent is:
```
{
Browser {
BrowserName: BrowserChrome,
Version: {
Major: 45,
Minor: 0,
Patch: 2454,
},
},
OS {
Platform: PlatformMac,
Name: OSMacOSX,
Version: {
Major: 10,
Minor: 10,
Patch: 5,
},
},
DeviceType: DeviceComputer,
}
```
**Usage note:** There are some OSes that do not return a version, see docs below. Linux is typically not reported with a specific Linux distro name or version.
#### Browser Name
* `BrowserChrome` - Google [Chrome](https://en.wikipedia.org/wiki/Google_Chrome), [Chromium](https://en.wikipedia.org/wiki/Chromium_(web_browser))
* `BrowserSafari` - Apple [Safari](https://en.wikipedia.org/wiki/Safari_(web_browser)), Google Search ([GSA](https://itunes.apple.com/us/app/google/id284815942))
* `BrowserIE` - Microsoft [Internet Explorer](https://en.wikipedia.org/wiki/Internet_Explorer), [Edge](https://en.wikipedia.org/wiki/Microsoft_Edge)
* `BrowserFirefox` - Mozilla [Firefox](https://en.wikipedia.org/wiki/Firefox), GNU [IceCat](https://en.wikipedia.org/wiki/GNU_IceCat), [Iceweasel](https://en.wikipedia.org/wiki/Mozilla_Corporation_software_rebranded_by_the_Debian_project#Iceweasel), [Seamonkey](https://en.wikipedia.org/wiki/SeaMonkey)
* `BrowserAndroid` - Android [WebView](https://developer.chrome.com/multidevice/webview/overview) (Android OS <4.4 only)
* `BrowserOpera` - [Opera](https://en.wikipedia.org/wiki/Opera_(web_browser))
* `BrowserUCBrowser` - [UC Browser](https://en.wikipedia.org/wiki/UC_Browser)
* `BrowserSilk` - Amazon [Silk](https://en.wikipedia.org/wiki/Amazon_Silk)
* `BrowserSpotify` - [Spotify](https://en.wikipedia.org/wiki/Spotify#Clients) desktop client
* `BrowserBlackberry` - RIM [BlackBerry](https://en.wikipedia.org/wiki/BlackBerry)
* `BrowserUnknown` - Unknown
#### Browser Version
Browser version returns an `unint8` of the major version attribute of the User-Agent String. For example Chrome 45.0.23423 would return `45`. The intention is to support math operators with versions, such as "do XYZ for Chrome version >23".
Unknown version is returned as `0`.
#### Platform
* `PlatformWindows` - Microsoft Windows
* `PlatformMac` - Apple Macintosh
* `PlatformLinux` - Linux, including Android and other OSes
* `PlatformiPad` - Apple iPad
* `PlatformiPhone` - Apple iPhone
* `PlatformBlackberry` - RIM Blackberry
* `PlatformWindowsPhone` Microsoft Windows Phone & Mobile
* `PlatformKindle` - Amazon Kindle & Kindle Fire
* `PlatformPlaystation` - Sony Playstation, Vita, PSP
* `PlatformXbox` - Microsoft Xbox - `PlatformXbox`
* `PlatformNintendo` - Nintendo DS, Wii, etc.
* `PlatformUnknown` - Unknown
#### OS Name
* `OSWindows`
* `OSMacOSX` - includes "macOS Sierra"
* `OSiOS`
* `OSAndroid`
* `OSChromeOS`
* `OSWebOS`
* `OSLinux`
* `OSPlaystation`
* `OSXbox`
* `OSNintendo`
* `OSUnknown`
#### OS Version
OS X major version is alway 10 with consecutive minor versions indicating release releases (10 - Yosemite, 11 - El Capitain, 12 Sierra, etc). Windows version is NT version. `Version{0, 0, 0}` indicated version is unknown or not evaluated.
Versions can be compared using `Less` function: `if ver1.Less(ver2) {}`
Here are some examples across the platform, os.name, and os.version:
* For Windows XP (Windows NT 5.1), "`PlatformWindows`" is the platform, "`OSWindows`" is the name, and `{5, 1, 0}` the version.
* For OS X 10.5.1, "`PlatformMac`" is the platform, "`OSMacOSX`" the name, and `{10, 5, 1}` the version.
* For Android 5.1, "`PlatformLinux`" is the platform, "`OSAndroid`" is the name, and `{5, 1, 0}` the version.
* For iOS 5.1, "`PlatformiPhone`" or "`PlatformiPad`" is the platform, "`OSiOS`" is the name, and `{5, 1, 0}` the version.
###### Windows Version Guide
* Windows 10 - `{10, 0, 0}`
* Windows 8.1 - `{6, 3, 0}`
* Windows 8 - `{6, 2, 0}`
* Windows 7 - `{6, 1, 0}`
* Windows Vista - `{6, 0, 0}`
* Windows XP - `{5, 1, 0}` or `{5, 2, 0}`
* Windows 2000 - `{5, 0, 0}`
Windows 95, 98, and ME represent 0.01% of traffic worldwide and are not available through this package at this time.
#### DeviceType
DeviceType is typically quite accurate, though determining between phones and tablets on Android is not always possible due to how some vendors design their UA strings. A mobile Android device without tablet indicator defaults to being classified as a phone. DeviceTV supports major brands such as Philips, Sharp, Vizio and steaming boxes such as Apple, Google, Roku, Amazon.
* `DeviceComputer`
* `DevicePhone`
* `DeviceTablet`
* `DeviceTV`
* `DeviceConsole`
* `DeviceWearable`
* `DeviceUnknown`
## Example Combinations of Attributes
* Surface RT -> `OSWindows8`, `DeviceTablet`, OSVersion >= `6`
* Android Tablet -> `OSAndroid`, `DeviceTablet`
* Microsoft Edge -> `BrowserIE`, BrowserVersion >= `12.0.0`
## To do
* Remove compiled regexp in favor of string.Contains wherever possible (lowers mem/alloc)
* Better version support on Firefox derivatives (e.g. SeaMonkey)
* Potential additional browser support:
* "NetFront" (1% share in India)
* "QQ Browser" (6.5% share in China)
* "Sogou Explorer" (5% share in China)
* "Maxthon" (1.5% share in China)
* "Nokia"
* Potential additional OS support:
* "Nokia" (5% share in India)
* "Series 40" (5.5% share in India)
* Windows 2003 Server
* iOS safari browser identification based on iOS version
* Add android version to browser identification
* old Macs
* "opera/9.64 (macintosh; ppc mac os x; u; en) presto/2.1.1"
* old Windows
* "mozilla/5.0 (windows nt 4.0; wow64) applewebkit/537.36 (khtml, like gecko) chrome/37.0.2049.0 safari/537.36"

192
vendor/github.com/avct/uasurfer/browser.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,192 @@
package uasurfer
import (
"strings"
)
// Browser struct contains the lowercase name of the browser, along
// with its browser version number. Browser are grouped together without
// consideration for device. For example, Chrome (Chrome/43.0) and Chrome for iOS
// (CriOS/43.0) would both return as "chrome" (name) and 43.0 (version). Similarly
// Internet Explorer 11 and Edge 12 would return as "ie" and "11" or "12", respectively.
// type Browser struct {
// Name BrowserName
// Version struct {
// Major int
// Minor int
// Patch int
// }
// }
// Retrieve browser name from UA strings
func (u *UserAgent) evalBrowserName(ua string) bool {
// Blackberry goes first because it reads as MSIE & Safari
if strings.Contains(ua, "blackberry") || strings.Contains(ua, "playbook") || strings.Contains(ua, "bb10") || strings.Contains(ua, "rim ") {
u.Browser.Name = BrowserBlackberry
return u.isBot()
}
if strings.Contains(ua, "applewebkit") {
switch {
case strings.Contains(ua, "opr/") || strings.Contains(ua, "opios/"):
u.Browser.Name = BrowserOpera
case strings.Contains(ua, "silk/"):
u.Browser.Name = BrowserSilk
case strings.Contains(ua, "edge/") || strings.Contains(ua, "iemobile/") || strings.Contains(ua, "msie "):
u.Browser.Name = BrowserIE
case strings.Contains(ua, "ucbrowser/") || strings.Contains(ua, "ucweb/"):
u.Browser.Name = BrowserUCBrowser
// Edge, Silk and other chrome-identifying browsers must evaluate before chrome, unless we want to add more overhead
case strings.Contains(ua, "chrome/") || strings.Contains(ua, "crios/") || strings.Contains(ua, "chromium/") || strings.Contains(ua, "crmo/"):
u.Browser.Name = BrowserChrome
case strings.Contains(ua, "android") && !strings.Contains(ua, "chrome/") && strings.Contains(ua, "version/") && !strings.Contains(ua, "like android"):
// Android WebView on Android >= 4.4 is purposefully being identified as Chrome above -- https://developer.chrome.com/multidevice/webview/overview
u.Browser.Name = BrowserAndroid
case strings.Contains(ua, "fxios"):
u.Browser.Name = BrowserFirefox
case strings.Contains(ua, " spotify/"):
u.Browser.Name = BrowserSpotify
// AppleBot uses webkit signature as well
case strings.Contains(ua, "applebot"):
u.Browser.Name = BrowserAppleBot
// presume it's safari unless an esoteric browser is being specified (webOSBrowser, SamsungBrowser, etc.)
case strings.Contains(ua, "like gecko") && strings.Contains(ua, "mozilla/") && strings.Contains(ua, "safari/") && !strings.Contains(ua, "linux") && !strings.Contains(ua, "android") && !strings.Contains(ua, "browser/") && !strings.Contains(ua, "os/"):
u.Browser.Name = BrowserSafari
// if we got this far and the device is iPhone or iPad, assume safari. Some agents don't actually contain the word "safari"
case strings.Contains(ua, "iphone") || strings.Contains(ua, "ipad"):
u.Browser.Name = BrowserSafari
// Google's search app on iPhone, leverages native Safari rather than Chrome
case strings.Contains(ua, " gsa/"):
u.Browser.Name = BrowserSafari
default:
goto notwebkit
}
return u.isBot()
}
notwebkit:
switch {
case strings.Contains(ua, "msie") || strings.Contains(ua, "trident"):
u.Browser.Name = BrowserIE
case strings.Contains(ua, "gecko") && (strings.Contains(ua, "firefox") || strings.Contains(ua, "iceweasel") || strings.Contains(ua, "seamonkey") || strings.Contains(ua, "icecat")):
u.Browser.Name = BrowserFirefox
case strings.Contains(ua, "presto") || strings.Contains(ua, "opera"):
u.Browser.Name = BrowserOpera
case strings.Contains(ua, "ucbrowser"):
u.Browser.Name = BrowserUCBrowser
case strings.Contains(ua, "applebot"):
u.Browser.Name = BrowserAppleBot
case strings.Contains(ua, "baiduspider"):
u.Browser.Name = BrowserBaiduBot
case strings.Contains(ua, "adidxbot") || strings.Contains(ua, "bingbot") || strings.Contains(ua, "bingpreview"):
u.Browser.Name = BrowserBingBot
case strings.Contains(ua, "duckduckbot"):
u.Browser.Name = BrowserDuckDuckGoBot
case strings.Contains(ua, "facebot") || strings.Contains(ua, "facebookexternalhit"):
u.Browser.Name = BrowserFacebookBot
case strings.Contains(ua, "googlebot"):
u.Browser.Name = BrowserGoogleBot
case strings.Contains(ua, "linkedinbot"):
u.Browser.Name = BrowserLinkedInBot
case strings.Contains(ua, "msnbot"):
u.Browser.Name = BrowserMsnBot
case strings.Contains(ua, "pingdom.com_bot"):
u.Browser.Name = BrowserPingdomBot
case strings.Contains(ua, "twitterbot"):
u.Browser.Name = BrowserTwitterBot
case strings.Contains(ua, "yandex") || strings.Contains(ua, "yadirectfetcher"):
u.Browser.Name = BrowserYandexBot
case strings.Contains(ua, "yahoo"):
u.Browser.Name = BrowserYahooBot
case strings.Contains(ua, "phantomjs"):
u.Browser.Name = BrowserBot
default:
u.Browser.Name = BrowserUnknown
}
return u.isBot()
}
// Retrieve browser version
// Methods used in order:
// 1st: look for generic version/#
// 2nd: look for browser-specific instructions (e.g. chrome/34)
// 3rd: infer from OS (iOS only)
func (u *UserAgent) evalBrowserVersion(ua string) {
// if there is a 'version/#' attribute with numeric version, use it -- except for Chrome since Android vendors sometimes hijack version/#
if u.Browser.Name != BrowserChrome && u.Browser.Version.findVersionNumber(ua, "version/") {
return
}
switch u.Browser.Name {
case BrowserChrome:
// match both chrome and crios
_ = u.Browser.Version.findVersionNumber(ua, "chrome/") || u.Browser.Version.findVersionNumber(ua, "crios/") || u.Browser.Version.findVersionNumber(ua, "crmo/")
case BrowserIE:
if u.Browser.Version.findVersionNumber(ua, "msie ") || u.Browser.Version.findVersionNumber(ua, "edge/") {
return
}
// get MSIE version from trident version https://en.wikipedia.org/wiki/Trident_(layout_engine)
if u.Browser.Version.findVersionNumber(ua, "trident/") {
// convert trident versions 3-7 to MSIE version
if (u.Browser.Version.Major >= 3) && (u.Browser.Version.Major <= 7) {
u.Browser.Version.Major += 4
}
}
case BrowserFirefox:
_ = u.Browser.Version.findVersionNumber(ua, "firefox/") || u.Browser.Version.findVersionNumber(ua, "fxios/")
case BrowserSafari: // executes typically if we're on iOS and not using a familiar browser
u.Browser.Version = u.OS.Version
// early Safari used a version number +1 to OS version
if (u.Browser.Version.Major <= 3) && (u.Browser.Version.Major >= 1) {
u.Browser.Version.Major++
}
case BrowserUCBrowser:
_ = u.Browser.Version.findVersionNumber(ua, "ucbrowser/")
case BrowserOpera:
_ = u.Browser.Version.findVersionNumber(ua, "opr/") || u.Browser.Version.findVersionNumber(ua, "opios/") || u.Browser.Version.findVersionNumber(ua, "opera/")
case BrowserSilk:
_ = u.Browser.Version.findVersionNumber(ua, "silk/")
case BrowserSpotify:
_ = u.Browser.Version.findVersionNumber(ua, "spotify/")
}
}

49
vendor/github.com/avct/uasurfer/const_string.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,49 @@
// Code generated by "stringer -type=DeviceType,BrowserName,OSName,Platform -output=const_string.go"; DO NOT EDIT.
package uasurfer
import "fmt"
const _DeviceType_name = "DeviceUnknownDeviceComputerDeviceTabletDevicePhoneDeviceConsoleDeviceWearableDeviceTV"
var _DeviceType_index = [...]uint8{0, 13, 27, 39, 50, 63, 77, 85}
func (i DeviceType) String() string {
if i < 0 || i >= DeviceType(len(_DeviceType_index)-1) {
return fmt.Sprintf("DeviceType(%d)", i)
}
return _DeviceType_name[_DeviceType_index[i]:_DeviceType_index[i+1]]
}
const _BrowserName_name = "BrowserUnknownBrowserChromeBrowserIEBrowserSafariBrowserFirefoxBrowserAndroidBrowserOperaBrowserBlackberryBrowserUCBrowserBrowserSilkBrowserNokiaBrowserNetFrontBrowserQQBrowserMaxthonBrowserSogouExplorerBrowserSpotifyBrowserBotBrowserAppleBotBrowserBaiduBotBrowserBingBotBrowserDuckDuckGoBotBrowserFacebookBotBrowserGoogleBotBrowserLinkedInBotBrowserMsnBotBrowserPingdomBotBrowserTwitterBotBrowserYandexBotBrowserYahooBot"
var _BrowserName_index = [...]uint16{0, 14, 27, 36, 49, 63, 77, 89, 106, 122, 133, 145, 160, 169, 183, 203, 217, 227, 242, 257, 271, 291, 309, 325, 343, 356, 373, 390, 406, 421}
func (i BrowserName) String() string {
if i < 0 || i >= BrowserName(len(_BrowserName_index)-1) {
return fmt.Sprintf("BrowserName(%d)", i)
}
return _BrowserName_name[_BrowserName_index[i]:_BrowserName_index[i+1]]
}
const _OSName_name = "OSUnknownOSWindowsPhoneOSWindowsOSMacOSXOSiOSOSAndroidOSBlackberryOSChromeOSOSKindleOSWebOSOSLinuxOSPlaystationOSXboxOSNintendoOSBot"
var _OSName_index = [...]uint8{0, 9, 23, 32, 40, 45, 54, 66, 76, 84, 91, 98, 111, 117, 127, 132}
func (i OSName) String() string {
if i < 0 || i >= OSName(len(_OSName_index)-1) {
return fmt.Sprintf("OSName(%d)", i)
}
return _OSName_name[_OSName_index[i]:_OSName_index[i+1]]
}
const _Platform_name = "PlatformUnknownPlatformWindowsPlatformMacPlatformLinuxPlatformiPadPlatformiPhonePlatformiPodPlatformBlackberryPlatformWindowsPhonePlatformPlaystationPlatformXboxPlatformNintendoPlatformBot"
var _Platform_index = [...]uint8{0, 15, 30, 41, 54, 66, 80, 92, 110, 130, 149, 161, 177, 188}
func (i Platform) String() string {
if i < 0 || i >= Platform(len(_Platform_index)-1) {
return fmt.Sprintf("Platform(%d)", i)
}
return _Platform_name[_Platform_index[i]:_Platform_index[i+1]]
}

60
vendor/github.com/avct/uasurfer/device.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,60 @@
package uasurfer
import (
"strings"
)
func (u *UserAgent) evalDevice(ua string) {
switch {
case u.OS.Platform == PlatformWindows || u.OS.Platform == PlatformMac || u.OS.Name == OSChromeOS:
if strings.Contains(ua, "mobile") || strings.Contains(ua, "touch") {
u.DeviceType = DeviceTablet // windows rt, linux haxor tablets
return
}
u.DeviceType = DeviceComputer
case u.OS.Platform == PlatformiPad || u.OS.Platform == PlatformiPod || strings.Contains(ua, "tablet") || strings.Contains(ua, "kindle/") || strings.Contains(ua, "playbook"):
u.DeviceType = DeviceTablet
case u.OS.Platform == PlatformiPhone || u.OS.Platform == PlatformBlackberry || strings.Contains(ua, "phone"):
u.DeviceType = DevicePhone
// long list of smarttv and tv dongle identifiers
case strings.Contains(ua, "tv") || strings.Contains(ua, "crkey") || strings.Contains(ua, "googletv") || strings.Contains(ua, "aftb") || strings.Contains(ua, "adt-") || strings.Contains(ua, "roku") || strings.Contains(ua, "viera") || strings.Contains(ua, "aquos") || strings.Contains(ua, "dtv") || strings.Contains(ua, "appletv") || strings.Contains(ua, "smarttv") || strings.Contains(ua, "tuner") || strings.Contains(ua, "smart-tv") || strings.Contains(ua, "hbbtv") || strings.Contains(ua, "netcast") || strings.Contains(ua, "vizio"):
u.DeviceType = DeviceTV
case u.OS.Name == OSAndroid:
// android phones report as "mobile", android tablets should not but often do -- http://android-developers.blogspot.com/2010/12/android-browser-user-agent-issues.html
if strings.Contains(ua, "mobile") {
u.DeviceType = DevicePhone
return
}
if strings.Contains(ua, "tablet") || strings.Contains(ua, "nexus 7") || strings.Contains(ua, "nexus 9") || strings.Contains(ua, "nexus 10") || strings.Contains(ua, "xoom") {
u.DeviceType = DeviceTablet
return
}
u.DeviceType = DevicePhone // default to phone
case u.OS.Platform == PlatformPlaystation || u.OS.Platform == PlatformXbox || u.OS.Platform == PlatformNintendo:
u.DeviceType = DeviceConsole
case strings.Contains(ua, "glass") || strings.Contains(ua, "watch") || strings.Contains(ua, "sm-v"):
u.DeviceType = DeviceWearable
// specifically above "mobile" string check as Kindle Fire tablets report as "mobile"
case u.Browser.Name == BrowserSilk || u.OS.Name == OSKindle && !strings.Contains(ua, "sd4930ur"):
u.DeviceType = DeviceTablet
case strings.Contains(ua, "mobile") || strings.Contains(ua, "touch") || strings.Contains(ua, " mobi") || strings.Contains(ua, "webos"): //anything "mobile"/"touch" that didn't get captured as tablet, console or wearable is presumed a phone
u.DeviceType = DevicePhone
case u.OS.Name == OSLinux: // linux goes last since it's in so many other device types (tvs, wearables, android-based stuff)
u.DeviceType = DeviceComputer
default:
u.DeviceType = DeviceUnknown
}
}

332
vendor/github.com/avct/uasurfer/system.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,332 @@
package uasurfer
import (
"regexp"
"strconv"
"strings"
)
var (
amazonFireFingerprint = regexp.MustCompile("\\s(k[a-z]{3,5}|sd\\d{4}ur)\\s") //tablet or phone
)
func (u *UserAgent) evalOS(ua string) bool {
s := strings.IndexRune(ua, '(')
e := strings.IndexRune(ua, ')')
if s > e {
s = 0
e = len(ua)
}
if e == -1 {
e = len(ua)
}
agentPlatform := ua[s+1 : e]
specsEnd := strings.Index(agentPlatform, ";")
var specs string
if specsEnd != -1 {
specs = agentPlatform[:specsEnd]
} else {
specs = agentPlatform
}
//strict OS & version identification
switch specs {
case "android":
u.evalLinux(ua, agentPlatform)
case "bb10", "playbook":
u.OS.Platform = PlatformBlackberry
u.OS.Name = OSBlackberry
case "x11", "linux":
u.evalLinux(ua, agentPlatform)
case "ipad", "iphone", "ipod touch", "ipod":
u.evaliOS(specs, agentPlatform)
case "macintosh":
u.evalMacintosh(ua)
default:
switch {
// Blackberry
case strings.Contains(ua, "blackberry") || strings.Contains(ua, "playbook"):
u.OS.Platform = PlatformBlackberry
u.OS.Name = OSBlackberry
// Windows Phone
case strings.Contains(agentPlatform, "windows phone "):
u.evalWindowsPhone(agentPlatform)
// Windows, Xbox
case strings.Contains(ua, "windows "):
u.evalWindows(ua)
// Kindle
case strings.Contains(ua, "kindle/") || amazonFireFingerprint.MatchString(agentPlatform):
u.OS.Platform = PlatformLinux
u.OS.Name = OSKindle
// Linux (broader attempt)
case strings.Contains(ua, "linux"):
u.evalLinux(ua, agentPlatform)
// WebOS (non-linux flagged)
case strings.Contains(ua, "webos") || strings.Contains(ua, "hpwos"):
u.OS.Platform = PlatformLinux
u.OS.Name = OSWebOS
// Nintendo
case strings.Contains(ua, "nintendo"):
u.OS.Platform = PlatformNintendo
u.OS.Name = OSNintendo
// Playstation
case strings.Contains(ua, "playstation") || strings.Contains(ua, "vita") || strings.Contains(ua, "psp"):
u.OS.Platform = PlatformPlaystation
u.OS.Name = OSPlaystation
// Android
case strings.Contains(ua, "android"):
u.evalLinux(ua, agentPlatform)
default:
u.OS.Platform = PlatformUnknown
u.OS.Name = OSUnknown
}
}
return u.isBot()
}
func (u *UserAgent) isBot() bool {
if u.OS.Platform == PlatformBot || u.OS.Name == OSBot {
u.DeviceType = DeviceComputer
return true
}
if u.Browser.Name >= BrowserBot && u.Browser.Name <= BrowserYahooBot {
u.OS.Platform = PlatformBot
u.OS.Name = OSBot
u.DeviceType = DeviceComputer
return true
}
return false
}
// evalLinux returns the `Platform`, `OSName` and Version of UAs with
// 'linux' listed as their platform.
func (u *UserAgent) evalLinux(ua string, agentPlatform string) {
switch {
// Kindle Fire
case strings.Contains(ua, "kindle") || amazonFireFingerprint.MatchString(agentPlatform):
// get the version of Android if available, though we don't call this OSAndroid
u.OS.Platform = PlatformLinux
u.OS.Name = OSKindle
u.OS.Version.findVersionNumber(agentPlatform, "android ")
// Android, Kindle Fire
case strings.Contains(ua, "android") || strings.Contains(ua, "googletv"):
// Android
u.OS.Platform = PlatformLinux
u.OS.Name = OSAndroid
u.OS.Version.findVersionNumber(agentPlatform, "android ")
// ChromeOS
case strings.Contains(ua, "cros"):
u.OS.Platform = PlatformLinux
u.OS.Name = OSChromeOS
// WebOS
case strings.Contains(ua, "webos") || strings.Contains(ua, "hpwos"):
u.OS.Platform = PlatformLinux
u.OS.Name = OSWebOS
// Linux, "Linux-like"
case strings.Contains(ua, "x11") || strings.Contains(ua, "bsd") || strings.Contains(ua, "suse") || strings.Contains(ua, "debian") || strings.Contains(ua, "ubuntu"):
u.OS.Platform = PlatformLinux
u.OS.Name = OSLinux
default:
u.OS.Platform = PlatformLinux
u.OS.Name = OSLinux
}
}
// evaliOS returns the `Platform`, `OSName` and Version of UAs with
// 'ipad' or 'iphone' listed as their platform.
func (u *UserAgent) evaliOS(uaPlatform string, agentPlatform string) {
switch uaPlatform {
// iPhone
case "iphone":
u.OS.Platform = PlatformiPhone
u.OS.Name = OSiOS
u.OS.getiOSVersion(agentPlatform)
// iPad
case "ipad":
u.OS.Platform = PlatformiPad
u.OS.Name = OSiOS
u.OS.getiOSVersion(agentPlatform)
// iPod
case "ipod touch", "ipod":
u.OS.Platform = PlatformiPod
u.OS.Name = OSiOS
u.OS.getiOSVersion(agentPlatform)
default:
u.OS.Platform = PlatformiPad
u.OS.Name = OSUnknown
}
}
func (u *UserAgent) evalWindowsPhone(agentPlatform string) {
u.OS.Platform = PlatformWindowsPhone
if u.OS.Version.findVersionNumber(agentPlatform, "windows phone os ") || u.OS.Version.findVersionNumber(agentPlatform, "windows phone ") {
u.OS.Name = OSWindowsPhone
} else {
u.OS.Name = OSUnknown
}
}
func (u *UserAgent) evalWindows(ua string) {
switch {
//Xbox -- it reads just like Windows
case strings.Contains(ua, "xbox"):
u.OS.Platform = PlatformXbox
u.OS.Name = OSXbox
if !u.OS.Version.findVersionNumber(ua, "windows nt ") {
u.OS.Version.Major = 6
u.OS.Version.Minor = 0
u.OS.Version.Patch = 0
}
// No windows version
case !strings.Contains(ua, "windows "):
u.OS.Platform = PlatformWindows
u.OS.Name = OSUnknown
case strings.Contains(ua, "windows nt ") && u.OS.Version.findVersionNumber(ua, "windows nt "):
u.OS.Platform = PlatformWindows
u.OS.Name = OSWindows
case strings.Contains(ua, "windows xp"):
u.OS.Platform = PlatformWindows
u.OS.Name = OSWindows
u.OS.Version.Major = 5
u.OS.Version.Minor = 1
u.OS.Version.Patch = 0
default:
u.OS.Platform = PlatformWindows
u.OS.Name = OSUnknown
}
}
func (u *UserAgent) evalMacintosh(uaPlatformGroup string) {
u.OS.Platform = PlatformMac
if i := strings.Index(uaPlatformGroup, "os x 10"); i != -1 {
u.OS.Name = OSMacOSX
u.OS.Version.parse(uaPlatformGroup[i+5:])
return
}
u.OS.Name = OSUnknown
}
func (v *Version) findVersionNumber(s string, m string) bool {
if ind := strings.Index(s, m); ind != -1 {
return v.parse(s[ind+len(m):])
}
return false
}
// getiOSVersion accepts the platform portion of a UA string and returns
// a Version.
func (o *OS) getiOSVersion(uaPlatformGroup string) {
if i := strings.Index(uaPlatformGroup, "cpu iphone os "); i != -1 {
o.Version.parse(uaPlatformGroup[i+14:])
return
}
if i := strings.Index(uaPlatformGroup, "cpu os "); i != -1 {
o.Version.parse(uaPlatformGroup[i+7:])
return
}
o.Version.parse(uaPlatformGroup)
}
// strToInt simply accepts a string and returns a `int`,
// with '0' being default.
func strToInt(str string) int {
i, _ := strconv.Atoi(str)
return i
}
// strToVer accepts a string and returns a Version,
// with {0, 0, 0} being default.
func (v *Version) parse(str string) bool {
if len(str) == 0 || str[0] < '0' || str[0] > '9' {
return false
}
for i := 0; i < 3; i++ {
empty := true
val := 0
l := len(str) - 1
for k, c := range str {
if c >= '0' && c <= '9' {
if empty {
val = int(c) - 48
empty = false
if k == l {
str = str[:0]
}
continue
}
if val == 0 {
if c == '0' {
if k == l {
str = str[:0]
}
continue
}
str = str[k:]
break
}
val = 10*val + int(c) - 48
if k == l {
str = str[:0]
}
continue
}
str = str[k+1:]
break
}
switch i {
case 0:
v.Major = val
case 1:
v.Minor = val
case 2:
v.Patch = val
}
}
return true
}

227
vendor/github.com/avct/uasurfer/uasurfer.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,227 @@
// Package uasurfer provides fast and reliable abstraction
// of HTTP User-Agent strings. The philosophy is to identify
// technologies that holds >1% market share, and to avoid
// expending resources and accuracy on guessing at esoteric UA
// strings.
package uasurfer
import "strings"
//go:generate stringer -type=DeviceType,BrowserName,OSName,Platform -output=const_string.go
// DeviceType (int) returns a constant.
type DeviceType int
// A complete list of supported devices in the
// form of constants.
const (
DeviceUnknown DeviceType = iota
DeviceComputer
DeviceTablet
DevicePhone
DeviceConsole
DeviceWearable
DeviceTV
)
// BrowserName (int) returns a constant.
type BrowserName int
// A complete list of supported web browsers in the
// form of constants.
const (
BrowserUnknown BrowserName = iota
BrowserChrome
BrowserIE
BrowserSafari
BrowserFirefox
BrowserAndroid
BrowserOpera
BrowserBlackberry
BrowserUCBrowser
BrowserSilk
BrowserNokia
BrowserNetFront
BrowserQQ
BrowserMaxthon
BrowserSogouExplorer
BrowserSpotify
BrowserBot // Bot list begins here
BrowserAppleBot
BrowserBaiduBot
BrowserBingBot
BrowserDuckDuckGoBot
BrowserFacebookBot
BrowserGoogleBot
BrowserLinkedInBot
BrowserMsnBot
BrowserPingdomBot
BrowserTwitterBot
BrowserYandexBot
BrowserYahooBot // Bot list ends here
)
// OSName (int) returns a constant.
type OSName int
// A complete list of supported OSes in the
// form of constants. For handling particular versions
// of operating systems (e.g. Windows 2000), see
// the README.md file.
const (
OSUnknown OSName = iota
OSWindowsPhone
OSWindows
OSMacOSX
OSiOS
OSAndroid
OSBlackberry
OSChromeOS
OSKindle
OSWebOS
OSLinux
OSPlaystation
OSXbox
OSNintendo
OSBot
)
// Platform (int) returns a constant.
type Platform int
// A complete list of supported platforms in the
// form of constants. Many OSes report their
// true platform, such as Android OS being Linux
// platform.
const (
PlatformUnknown Platform = iota
PlatformWindows
PlatformMac
PlatformLinux
PlatformiPad
PlatformiPhone
PlatformiPod
PlatformBlackberry
PlatformWindowsPhone
PlatformPlaystation
PlatformXbox
PlatformNintendo
PlatformBot
)
type Version struct {
Major int
Minor int
Patch int
}
func (v Version) Less(c Version) bool {
if v.Major < c.Major {
return true
}
if v.Major > c.Major {
return false
}
if v.Minor < c.Minor {
return true
}
if v.Minor > c.Minor {
return false
}
return v.Patch < c.Patch
}
type UserAgent struct {
Browser Browser
OS OS
DeviceType DeviceType
}
type Browser struct {
Name BrowserName
Version Version
}
type OS struct {
Platform Platform
Name OSName
Version Version
}
// Reset resets the UserAgent to it's zero value
func (ua *UserAgent) Reset() {
ua.Browser = Browser{}
ua.OS = OS{}
ua.DeviceType = DeviceUnknown
}
// Parse accepts a raw user agent (string) and returns the UserAgent.
func Parse(ua string) *UserAgent {
dest := new(UserAgent)
parse(ua, dest)
return dest
}
// ParseUserAgent is the same as Parse, but populates the supplied UserAgent.
// It is the caller's responsibility to call Reset() on the UserAgent before
// passing it to this function.
func ParseUserAgent(ua string, dest *UserAgent) {
parse(ua, dest)
}
func parse(ua string, dest *UserAgent) {
ua = normalise(ua)
switch {
case len(ua) == 0:
dest.OS.Platform = PlatformUnknown
dest.OS.Name = OSUnknown
dest.Browser.Name = BrowserUnknown
dest.DeviceType = DeviceUnknown
// stop on on first case returning true
case dest.evalOS(ua):
case dest.evalBrowserName(ua):
default:
dest.evalBrowserVersion(ua)
dest.evalDevice(ua)
}
}
// normalise normalises the user supplied agent string so that
// we can more easily parse it.
func normalise(ua string) string {
if len(ua) <= 1024 {
var buf [1024]byte
ascii := copyLower(buf[:len(ua)], ua)
if !ascii {
// Fall back for non ascii characters
return strings.ToLower(ua)
}
return string(buf[:len(ua)])
}
// Fallback for unusually long strings
return strings.ToLower(ua)
}
// copyLower copies a lowercase version of s to b. It assumes s contains only single byte characters
// and will panic if b is nil or is not long enough to contain all the bytes from s.
// It returns early with false if any characters were non ascii.
func copyLower(b []byte, s string) bool {
for j := 0; j < len(s); j++ {
c := s[j]
if c > 127 {
return false
}
if 'A' <= c && c <= 'Z' {
c += 'a' - 'A'
}
b[j] = c
}
return true
}

1064
vendor/github.com/avct/uasurfer/uasurfer_test.go сгенерированный поставляемый Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

8
vendor/github.com/dgryski/dgoogauth/googauth_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,7 +1,7 @@
package dgoogauth
import (
"strconv"
"fmt"
"testing"
"time"
)
@@ -199,11 +199,11 @@ func TestAuthenticate(t *testing.T) {
t0 = int64(time.Now().Unix() / 30)
}
c := ComputeCode(otpconf.Secret, t0)
code := fmt.Sprintf("%06d", c)
invalid := c + 1
attempts = []attempt{
{strconv.Itoa(invalid), false},
{strconv.Itoa(c), true},
{code + "1", false},
{code, true},
}
for _, a := range attempts {

6
vendor/github.com/go-ini/ini/file.go сгенерированный поставляемый
Просмотреть файл

@@ -345,6 +345,12 @@ func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
return nil, err
}
}
for _, val := range key.nestedValues {
if _, err := buf.WriteString(indent + " " + val + LineBreak); err != nil {
return nil, err
}
}
}
if PrettySection {

12
vendor/github.com/go-ini/ini/ini.go сгенерированный поставляемый
Просмотреть файл

@@ -32,7 +32,7 @@ const (
// Maximum allowed depth when recursively substituing variable names.
_DEPTH_VALUES = 99
_VERSION = "1.30.3"
_VERSION = "1.32.0"
)
// Version returns current package version literal.
@@ -134,8 +134,16 @@ type LoadOptions struct {
AllowBooleanKeys bool
// AllowShadows indicates whether to keep track of keys with same name under same section.
AllowShadows bool
// UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value"
// AllowNestedValues indicates whether to allow AWS-like nested values.
// Docs: http://docs.aws.amazon.com/cli/latest/topic/config-vars.html#nested-values
AllowNestedValues bool
// UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format
// when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value"
UnescapeValueDoubleQuotes bool
// UnescapeValueCommentSymbols indicates to unescape comment symbols (\# and \;) inside value to regular format
// when value is NOT surrounded by any quotes.
// Note: UNSTABLE, behavior might change to only unescape inside double quotes but may noy necessary at all.
UnescapeValueCommentSymbols bool
// Some INI formats allow group blocks that store a block of raw content that doesn't otherwise
// conform to key/value pairs. Specify the names of those blocks here.
UnparseableSections []string

13
vendor/github.com/go-ini/ini/ini_test.go сгенерированный поставляемый
Просмотреть файл

@@ -268,6 +268,19 @@ create_repo="创建了仓库 <a href=\"%s\">%s</a>"`))
})
})
Convey("Unescape comment symbols inside value", func() {
f, err := ini.LoadSources(ini.LoadOptions{
IgnoreInlineComment: true,
UnescapeValueCommentSymbols: true,
}, []byte(`
key = test value <span style="color: %s\; background: %s">more text</span>
`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.Section("").Key("key").String(), ShouldEqual, `test value <span style="color: %s; background: %s">more text</span>`)
})
Convey("Allow unparseable sections", func() {
f, err := ini.LoadSources(ini.LoadOptions{
Insensitive: true,

26
vendor/github.com/go-ini/ini/key.go сгенерированный поставляемый
Просмотреть файл

@@ -34,6 +34,8 @@ type Key struct {
isShadow bool
shadows []*Key
nestedValues []string
}
// newKey simply return a key object with given values.
@@ -66,6 +68,22 @@ func (k *Key) AddShadow(val string) error {
return k.addShadow(val)
}
func (k *Key) addNestedValue(val string) error {
if k.isAutoIncrement || k.isBooleanType {
return errors.New("cannot add nested value to auto-increment or boolean key")
}
k.nestedValues = append(k.nestedValues, val)
return nil
}
func (k *Key) AddNestedValue(val string) error {
if !k.s.f.options.AllowNestedValues {
return errors.New("nested value is not allowed")
}
return k.addNestedValue(val)
}
// ValueMapper represents a mapping function for values, e.g. os.ExpandEnv
type ValueMapper func(string) string
@@ -92,6 +110,12 @@ func (k *Key) ValueWithShadows() []string {
return vals
}
// NestedValues returns nested values stored in the key.
// It is possible returned value is nil if no nested values stored in the key.
func (k *Key) NestedValues() []string {
return k.nestedValues
}
// transformValue takes a raw value and transforms to its final string.
func (k *Key) transformValue(val string) string {
if k.s.f.ValueMapper != nil {
@@ -114,7 +138,7 @@ func (k *Key) transformValue(val string) string {
// Search in the same section.
nk, err := k.s.GetKey(noption)
if err != nil {
if err != nil || k == nk {
// Search again in default section.
nk, _ = k.s.f.Section("").GetKey(noption)
}

43
vendor/github.com/go-ini/ini/key_test.go сгенерированный поставляемый
Просмотреть файл

@@ -15,6 +15,7 @@
package ini_test
import (
"bytes"
"fmt"
"strings"
"testing"
@@ -478,3 +479,45 @@ func TestKey_SetValue(t *testing.T) {
So(k.Value(), ShouldEqual, "ini.v1")
})
}
func TestKey_NestedValues(t *testing.T) {
Convey("Read and write nested values", t, func() {
f, err := ini.LoadSources(ini.LoadOptions{
AllowNestedValues: true,
}, []byte(`
aws_access_key_id = foo
aws_secret_access_key = bar
region = us-west-2
s3 =
max_concurrent_requests=10
max_queue_size=1000`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.Section("").Key("s3").NestedValues(), ShouldResemble, []string{"max_concurrent_requests=10", "max_queue_size=1000"})
var buf bytes.Buffer
_, err = f.WriteTo(&buf)
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `aws_access_key_id = foo
aws_secret_access_key = bar
region = us-west-2
s3 =
max_concurrent_requests=10
max_queue_size=1000
`)
})
}
func TestRecursiveValues(t *testing.T) {
Convey("Recursive values should not reflect on same key", t, func() {
f, err := ini.Load([]byte(`
NAME = ini
[package]
NAME = %(NAME)s`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(f.Section("package").Key("NAME").String(), ShouldEqual, "ini")
})
}

31
vendor/github.com/go-ini/ini/parser.go сгенерированный поставляемый
Просмотреть файл

@@ -193,7 +193,9 @@ func hasSurroundedQuote(in string, quote byte) bool {
strings.IndexByte(in[1:], quote) == len(in)-2
}
func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment, unescapeValueDoubleQuotes bool) (string, error) {
func (p *parser) readValue(in []byte,
ignoreContinuation, ignoreInlineComment, unescapeValueDoubleQuotes, unescapeValueCommentSymbols bool) (string, error) {
line := strings.TrimLeftFunc(string(in), unicode.IsSpace)
if len(line) == 0 {
return "", nil
@@ -243,6 +245,13 @@ func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment, u
if hasSurroundedQuote(line, '\'') ||
hasSurroundedQuote(line, '"') {
line = line[1 : len(line)-1]
} else if len(valQuote) == 0 && unescapeValueCommentSymbols {
if strings.Contains(line, `\;`) {
line = strings.Replace(line, `\;`, ";", -1)
}
if strings.Contains(line, `\#`) {
line = strings.Replace(line, `\#`, "#", -1)
}
}
return line, nil
}
@@ -261,6 +270,10 @@ func (f *File) parse(reader io.Reader) (err error) {
}
section, _ := f.NewSection(name)
// This "last" is not strictly equivalent to "previous one" if current key is not the first nested key
var isLastValueEmpty bool
var lastRegularKey *Key
var line []byte
var inUnparseableSection bool
for !p.isEOF {
@@ -269,6 +282,14 @@ func (f *File) parse(reader io.Reader) (err error) {
return err
}
if f.options.AllowNestedValues &&
isLastValueEmpty && len(line) > 0 {
if line[0] == ' ' || line[0] == '\t' {
lastRegularKey.addNestedValue(string(bytes.TrimSpace(line)))
continue
}
}
line = bytes.TrimLeftFunc(line, unicode.IsSpace)
if len(line) == 0 {
continue
@@ -333,7 +354,8 @@ func (f *File) parse(reader io.Reader) (err error) {
kname, err := p.readValue(line,
f.options.IgnoreContinuation,
f.options.IgnoreInlineComment,
f.options.UnescapeValueDoubleQuotes)
f.options.UnescapeValueDoubleQuotes,
f.options.UnescapeValueCommentSymbols)
if err != nil {
return err
}
@@ -359,10 +381,12 @@ func (f *File) parse(reader io.Reader) (err error) {
value, err := p.readValue(line[offset:],
f.options.IgnoreContinuation,
f.options.IgnoreInlineComment,
f.options.UnescapeValueDoubleQuotes)
f.options.UnescapeValueDoubleQuotes,
f.options.UnescapeValueCommentSymbols)
if err != nil {
return err
}
isLastValueEmpty = len(value) == 0
key, err := section.NewKey(kname, value)
if err != nil {
@@ -371,6 +395,7 @@ func (f *File) parse(reader io.Reader) (err error) {
key.isAutoIncrement = isAutoIncr
key.Comment = strings.TrimSpace(p.comment.String())
p.comment.Reset()
lastRegularKey = key
}
return nil
}

3
vendor/github.com/golang/protobuf/jsonpb/jsonpb.go сгенерированный поставляемый
Просмотреть файл

@@ -193,8 +193,7 @@ func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeU
// "Generated output always contains 3, 6, or 9 fractional digits,
// depending on required precision."
s, ns := s.Field(0).Int(), s.Field(1).Int()
d := time.Duration(s)*time.Second + time.Duration(ns)*time.Nanosecond
x := fmt.Sprintf("%.9f", d.Seconds())
x := fmt.Sprintf("%d.%09d", s, ns)
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, "000")
out.write(`"`)

1
vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go сгенерированный поставляемый
Просмотреть файл

@@ -407,6 +407,7 @@ var marshalingTests = []struct {
{"Any with WKT", marshaler, anyWellKnown, anyWellKnownJSON},
{"Any with WKT and indent", marshalerAllOptions, anyWellKnown, anyWellKnownPrettyJSON},
{"Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}, `{"dur":"3.000s"}`},
{"Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 100000000, Nanos: 1}}, `{"dur":"100000000.000000001s"}`},
{"Struct", marshaler, &pb.KnownTypes{St: &stpb.Struct{
Fields: map[string]*stpb.Value{
"one": {Kind: &stpb.Value_StringValue{"loneliest number"}},

2
vendor/github.com/hashicorp/go-multierror/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -3,7 +3,7 @@ sudo: false
language: go
go:
- 1.6
- 1.x
branches:
only:

4
vendor/github.com/hashicorp/memberlist/memberlist.go сгенерированный поставляемый
Просмотреть файл

@@ -639,7 +639,9 @@ func (m *Memberlist) Shutdown() error {
// Shut down the transport first, which should block until it's
// completely torn down. If we kill the memberlist-side handlers
// those I/O handlers might get stuck.
m.transport.Shutdown()
if err := m.transport.Shutdown(); err != nil {
m.logger.Printf("[ERR] Failed to shutdown transport: %v", err)
}
// Now tear down everything else.
atomic.StoreInt32(&m.shutdown, 1)

2
vendor/github.com/hashicorp/memberlist/net.go сгенерированный поставляемый
Просмотреть файл

@@ -1059,7 +1059,7 @@ func (m *Memberlist) readUserMsg(bufConn io.Reader, dec *codec.Decoder) error {
// operations, given the deadline. The bool return parameter is true if we
// we able to round trip a ping to the other node.
func (m *Memberlist) sendPingAndWaitForAck(addr string, ping ping, deadline time.Time) (bool, error) {
conn, err := m.transport.DialTimeout(addr, m.config.TCPTimeout)
conn, err := m.transport.DialTimeout(addr, deadline.Sub(time.Now()))
if err != nil {
// If the node is actually dead we expect this to fail, so we
// shouldn't spam the logs with it. After this point, errors

14
vendor/github.com/hashicorp/memberlist/state.go сгенерированный поставляемый
Просмотреть файл

@@ -251,10 +251,17 @@ func (m *Memberlist) probeNode(node *nodeState) {
nackCh := make(chan struct{}, m.config.IndirectChecks+1)
m.setProbeChannels(ping.SeqNo, ackCh, nackCh, probeInterval)
// Mark the sent time here, which should be after any pre-processing but
// before system calls to do the actual send. This probably over-reports
// a bit, but it's the best we can do. We had originally put this right
// after the I/O, but that would sometimes give negative RTT measurements
// which was not desirable.
sent := time.Now()
// Send a ping to the node. If this node looks like it's suspect or dead,
// also tack on a suspect message so that it has a chance to refute as
// soon as possible.
deadline := time.Now().Add(probeInterval)
deadline := sent.Add(probeInterval)
addr := node.Address()
if node.State == stateAlive {
if err := m.encodeAndSendMsg(addr, pingMsg, &ping); err != nil {
@@ -284,11 +291,6 @@ func (m *Memberlist) probeNode(node *nodeState) {
}
}
// Mark the sent time here, which should be after any pre-processing and
// system calls to do the actual send. This probably under-reports a bit,
// but it's the best we can do.
sent := time.Now()
// Arrange for our self-awareness to get updated. At this point we've
// sent the ping, so any return statement means the probe succeeded
// which will improve our health until we get to the failure scenarios

2
vendor/github.com/hashicorp/memberlist/transport.go сгенерированный поставляемый
Просмотреть файл

@@ -17,7 +17,7 @@ type Packet struct {
// Timestamp is the time when the packet was received. This should be
// taken as close as possible to the actual receipt time to help make an
// accurate RTT measurements during probes.
// accurate RTT measurement during probes.
Timestamp time.Time
}

14
vendor/github.com/lib/pq/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -16,7 +16,7 @@ env:
- PQGOSSLTESTS=1
- PQSSLCERTTEST_PATH=$PWD/certs
- PGHOST=127.0.0.1
- MEGACHECK_VERSION=2017.1
- MEGACHECK_VERSION=2017.2.1
matrix:
- PGVERSION=10
- PGVERSION=9.6
@@ -46,15 +46,13 @@ script:
- >
goimports -d -e $(find -name '*.go') | awk '{ print } END { exit NR == 0 ? 0 : 1 }'
- go vet ./...
# For compatibility with Go 1.5, launch only if megacheck is present,
# ignore SA1019 (deprecation warnings) in conn_test.go (we have to use the
# deprecated driver.Execer and driver.Queryer interfaces) and S1024
# (time.Until) everywhere.
# For compatibility with Go 1.5, launch only if megacheck is present.
- >
which megacheck > /dev/null
&& megacheck -ignore 'github.com/lib/pq/conn_test.go:SA1019 github.com/lib/pq/*.go:S1024' ./...
which megacheck > /dev/null && megacheck -go 1.5 ./...
|| echo 'megacheck is not supported, skipping check'
# For compatibility with Go 1.5, launch only if golint is present.
- which golint > /dev/null && golint ./... || echo 'golint is not supported, skipping check'
- >
which golint > /dev/null && golint ./...
|| echo 'golint is not supported, skipping check'
- PQTEST_BINARY_PARAMETERS=no go test -race -v ./...
- PQTEST_BINARY_PARAMETERS=yes go test -race -v ./...

2
vendor/github.com/lib/pq/doc.go сгенерированный поставляемый
Просмотреть файл

@@ -239,7 +239,7 @@ for more information). Note that the channel name will be truncated to 63
bytes by the PostgreSQL server.
You can find a complete, working example of Listener usage at
http://godoc.org/github.com/lib/pq/examples/listen.
http://godoc.org/github.com/lib/pq/example/listen.
*/
package pq

8
vendor/github.com/miekg/dns/.codecov.yml сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,8 @@
coverage:
status:
project:
default:
target: 40%
threshold: null
patch: false
changes: false

21
vendor/github.com/miekg/dns/Gopkg.lock сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,21 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
branch = "master"
name = "golang.org/x/crypto"
packages = ["ed25519","ed25519/internal/edwards25519"]
revision = "b080dc9a8c480b08e698fb1219160d598526310f"
[[projects]]
branch = "master"
name = "golang.org/x/net"
packages = ["bpf","internal/iana","internal/socket","ipv4","ipv6"]
revision = "894f8ed5849b15b810ae41e9590a0d05395bba27"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "c4abc38abaeeeeb9be92455c9c02cae32841122b8982aaa067ef25bb8e86ff9d"
solver-name = "gps-cdcl"
solver-version = 1

26
vendor/github.com/miekg/dns/Gopkg.toml сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,26 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
[[constraint]]
branch = "master"
name = "golang.org/x/crypto"

33
vendor/github.com/miekg/dns/Makefile.fuzz сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,33 @@
# Makefile for fuzzing
#
# Use go-fuzz and needs the tools installed.
# See https://blog.cloudflare.com/dns-parser-meet-go-fuzzer/
#
# Installing go-fuzz:
# $ make -f Makefile.fuzz get
# Installs:
# * github.com/dvyukov/go-fuzz/go-fuzz
# * get github.com/dvyukov/go-fuzz/go-fuzz-build
all: build
.PHONY: build
build:
go-fuzz-build -tags fuzz github.com/miekg/dns
.PHONY: build-newrr
build-newrr:
go-fuzz-build -func FuzzNewRR -tags fuzz github.com/miekg/dns
.PHONY: fuzz
fuzz:
go-fuzz -bin=dns-fuzz.zip -workdir=fuzz
.PHONY: get
get:
go get github.com/dvyukov/go-fuzz/go-fuzz
go get github.com/dvyukov/go-fuzz/go-fuzz-build
.PHONY: clean
clean:
rm *-fuzz.zip

52
vendor/github.com/miekg/dns/Makefile.release сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,52 @@
# Makefile for releasing.
#
# The release is controlled from version.go. The version found there is
# used to tag the git repo, we're not building any artifects so there is nothing
# to upload to github.
#
# * Up the version in version.go
# * Run: make -f Makefile.release release
# * will *commit* your change with 'Release $VERSION'
# * push to github
#
define GO
//+build ignore
package main
import (
"fmt"
"github.com/miekg/dns"
)
func main() {
fmt.Println(dns.Version.String())
}
endef
$(file > version_release.go,$(GO))
VERSION:=$(shell go run version_release.go)
TAG="v$(VERSION)"
all:
@echo Use the \'release\' target to start a release $(VERSION)
rm -f version_release.go
.PHONY: release
release: commit push
@echo Released $(VERSION)
rm -f version_release.go
.PHONY: commit
commit:
@echo Committing release $(VERSION)
git commit -am"Release $(VERSION)"
git tag $(TAG)
.PHONY: push
push:
@echo Pushing release $(VERSION) to master
git push --tags
git push

5
vendor/github.com/miekg/dns/README.md сгенерированный поставляемый
Просмотреть файл

@@ -74,7 +74,7 @@ Send pull request if you want to be listed here.
* Parsing RRs ~ 100K RR/s, that's 5M records in about 50 seconds;
* Server side programming (mimicking the net/http package);
* Client side programming;
* DNSSEC: signing, validating and key generation for DSA, RSA and ECDSA;
* DNSSEC: signing, validating and key generation for DSA, RSA, ECDSA and Ed25519;
* EDNS0, NSID, Cookies;
* AXFR/IXFR;
* TSIG, SIG(0);
@@ -150,10 +150,13 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
* 6975 - Algorithm Understanding in DNSSEC
* 7043 - EUI48/EUI64 records
* 7314 - DNS (EDNS) EXPIRE Option
* 7477 - CSYNC RR
* 7828 - edns-tcp-keepalive EDNS0 Option
* 7553 - URI record
* 7858 - DNS over TLS: Initiation and Performance Considerations
* 7871 - EDNS0 Client Subnet
* 7873 - Domain Name System (DNS) Cookies (draft-ietf-dnsop-cookies)
* 8080 - EdDSA for DNSSEC
## Loosely based upon

19
vendor/github.com/miekg/dns/client.go сгенерированный поставляемый
Просмотреть файл

@@ -20,7 +20,7 @@ const tcpIdleTimeout time.Duration = 8 * time.Second
type Conn struct {
net.Conn // a net.Conn holding the connection
UDPSize uint16 // minimum receive buffer for UDP messages
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
rtt time.Duration
t time.Time
tsigRequestMAC string
@@ -39,7 +39,7 @@ type Client struct {
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
group singleflight
}
@@ -192,8 +192,10 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
}
// ReadMsg reads a message from the connection co.
// If the received message contains a TSIG record the transaction
// signature is verified.
// If the received message contains a TSIG record the transaction signature
// is verified. This method always tries to return the message, however if an
// error is returned there are no guarantees that the returned message is a
// valid representation of the packet read.
func (co *Conn) ReadMsg() (*Msg, error) {
p, err := co.ReadMsgHeader(nil)
if err != nil {
@@ -202,13 +204,10 @@ func (co *Conn) ReadMsg() (*Msg, error) {
m := new(Msg)
if err := m.Unpack(p); err != nil {
// If ErrTruncated was returned, we still want to allow the user to use
// If an error was returned, we still want to allow the user to use
// the message, but naively they can just check err if they don't want
// to use a truncated message
if err == ErrTruncated {
return m, err
}
return nil, err
// to use an erroneous message
return m, err
}
if t := m.IsTsig(); t != nil {
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {

10
vendor/github.com/miekg/dns/client_test.go сгенерированный поставляемый
Просмотреть файл

@@ -458,12 +458,12 @@ func TestTruncatedMsg(t *testing.T) {
t.Errorf("error should not be ErrTruncated from question cutoff unpack: %v", err)
}
// Finally, if we only have the header, we should still return an error
// Finally, if we only have the header, we don't return an error.
buf1 = buf[:12]
r = new(Msg)
if err = r.Unpack(buf1); err == nil || err != ErrTruncated {
t.Errorf("error not ErrTruncated from header-only unpack: %v", err)
if err = r.Unpack(buf1); err != nil {
t.Errorf("from header-only unpack should not return an error: %v", err)
}
}
@@ -568,11 +568,11 @@ func TestConcurrentExchanges(t *testing.T) {
wg.Add(len(r))
for i := 0; i < len(r); i++ {
go func(i int) {
defer wg.Done()
r[i], _, _ = c.Exchange(m.Copy(), addrstr)
if r[i] == nil {
t.Fatalf("response %d is nil", i)
t.Errorf("response %d is nil", i)
}
wg.Done()
}(i)
}
select {

6
vendor/github.com/miekg/dns/clientconfig.go сгенерированный поставляемый
Просмотреть файл

@@ -79,8 +79,10 @@ func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error) {
switch {
case len(s) >= 6 && s[:6] == "ndots:":
n, _ := strconv.Atoi(s[6:])
if n < 1 {
n = 1
if n < 0 {
n = 0
} else if n > 15 {
n = 15
}
c.Ndots = n
case len(s) >= 8 && s[:8] == "timeout:":

54
vendor/github.com/miekg/dns/clientconfig_test.go сгенерированный поставляемый
Просмотреть файл

@@ -40,6 +40,28 @@ func testConfig(t *testing.T, data string) {
func TestNameserver(t *testing.T) { testConfig(t, normal) }
func TestMissingFinalNewLine(t *testing.T) { testConfig(t, missingNewline) }
func TestNdots(t *testing.T) {
ndotsVariants := map[string]int{
"options ndots:0": 0,
"options ndots:1": 1,
"options ndots:15": 15,
"options ndots:16": 15,
"options ndots:-1": 0,
"": 1,
}
for data := range ndotsVariants {
cc, err := ClientConfigFromReader(strings.NewReader(data))
if err != nil {
t.Errorf("error parsing resolv.conf: %v", err)
}
if cc.Ndots != ndotsVariants[data] {
t.Errorf("Ndots not properly parsed: (Expected: %d / Was: %d)", ndotsVariants[data], cc.Ndots)
}
}
}
func TestReadFromFile(t *testing.T) {
tempDir, err := ioutil.TempDir("", "")
if err != nil {
@@ -67,7 +89,7 @@ func TestReadFromFile(t *testing.T) {
}
}
func TestNameList(t *testing.T) {
func TestNameListNdots1(t *testing.T) {
cfg := ClientConfig{
Ndots: 1,
}
@@ -91,10 +113,18 @@ func TestNameList(t *testing.T) {
} else if names[1] != "miek.nl.test." {
t.Errorf("NameList didn't return search last: %v", names[1])
}
}
func TestNameListNdots2(t *testing.T) {
cfg := ClientConfig{
Ndots: 2,
}
cfg.Ndots = 2
// Sent domain has less than NDots and search
names = cfg.NameList("miek.nl")
cfg.Search = []string{
"test",
}
names := cfg.NameList("miek.nl")
if len(names) != 2 {
t.Errorf("NameList returned != 2 names: %v", names)
} else if names[0] != "miek.nl.test." {
@@ -103,3 +133,21 @@ func TestNameList(t *testing.T) {
t.Errorf("NameList didn't return sent domain last: %v", names[1])
}
}
func TestNameListNdots0(t *testing.T) {
cfg := ClientConfig{
Ndots: 0,
}
cfg.Search = []string{
"test",
}
// Sent domain has less than NDots and search
names := cfg.NameList("miek")
if len(names) != 2 {
t.Errorf("NameList returned != 2 names: %v", names)
} else if names[0] != "miek." {
t.Errorf("NameList didn't return search first: %v", names[0])
} else if names[1] != "miek.test." {
t.Errorf("NameList didn't return sent domain last: %v", names[1])
}
}

3
vendor/github.com/miekg/dns/compress_generate.go сгенерированный поставляемый
Просмотреть файл

@@ -18,8 +18,7 @@ import (
)
var packageHdr = `
// *** DO NOT MODIFY ***
// AUTOGENERATED BY go generate from compress_generate.go
// Code generated by "go run compress_generate.go"; DO NOT EDIT.
package dns

7
vendor/github.com/miekg/dns/defaults.go сгенерированный поставляемый
Просмотреть файл

@@ -273,8 +273,11 @@ func (t Type) String() string {
// String returns the string representation for the class c.
func (c Class) String() string {
if c1, ok := ClassToString[uint16(c)]; ok {
return c1
if s, ok := ClassToString[uint16(c)]; ok {
// Only emit mnemonics when they are unambiguous, specically ANY is in both.
if _, ok := StringToType[s]; !ok {
return s
}
}
return "CLASS" + strconv.Itoa(int(c))
}

61
vendor/github.com/miekg/dns/dns_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,6 +1,7 @@
package dns
import (
"bytes"
"encoding/hex"
"net"
"testing"
@@ -317,8 +318,9 @@ func TestNoRdataPack(t *testing.T) {
func TestNoRdataUnpack(t *testing.T) {
data := make([]byte, 1024)
for typ, fn := range TypeToRR {
if typ == TypeSOA || typ == TypeTSIG {
if typ == TypeSOA || typ == TypeTSIG || typ == TypeTKEY {
// SOA, TSIG will not be seen (like this) in dyn. updates?
// TKEY requires length fields to be present for the Key and OtherData fields
continue
}
r := fn()
@@ -405,3 +407,60 @@ func TestMsgPackBuffer(t *testing.T) {
}
}
}
// Make sure we can decode a TKEY packet from the string, modify the RR, and then pack it again.
func TestTKEY(t *testing.T) {
// An example TKEY RR captured. There is no known accepted standard text format for a TKEY
// record so we do this from a hex string instead of from a text readable string.
tkeyStr := "0737362d6d732d370932322d3332633233332463303439663961662d633065612d313165372d363839362d6463333937396666656666640000f900ff0000000000d2086773732d747369670059fd01f359fe53730003000000b8a181b53081b2a0030a0100a10b06092a864882f712010202a2819d04819a60819706092a864886f71201020202006f8187308184a003020105a10302010fa2783076a003020112a26f046db29b1b1d2625da3b20b49dafef930dd1e9aad335e1c5f45dcd95e0005d67a1100f3e573d70506659dbed064553f1ab890f68f65ae10def0dad5b423b39f240ebe666f2886c5fe03819692d29182bbed87b83e1f9d16b7334ec16a3c4fc5ad4a990088e0be43f0c6957916f5fe60000"
tkeyBytes, err := hex.DecodeString(tkeyStr)
if err != nil {
t.Fatal("unable to decode TKEY string ", err)
}
// Decode the RR
rr, tkeyLen, unPackErr := UnpackRR(tkeyBytes, 0)
if unPackErr != nil {
t.Fatal("unable to decode TKEY RR", unPackErr)
}
// Make sure it's a TKEY record
if rr.Header().Rrtype != TypeTKEY {
t.Fatal("Unable to decode TKEY")
}
// Make sure we get back the same length
if rr.len() != len(tkeyBytes) {
t.Fatalf("Lengths don't match %d != %d", rr.len(), len(tkeyBytes))
}
// make space for it with some fudge room
msg := make([]byte, tkeyLen+1000)
offset, packErr := PackRR(rr, msg, 0, nil, false)
if packErr != nil {
t.Fatal("unable to pack TKEY RR", packErr)
}
if offset != len(tkeyBytes) {
t.Fatalf("mismatched TKEY RR size %d != %d", len(tkeyBytes), offset)
}
if bytes.Compare(tkeyBytes, msg[0:offset]) != 0 {
t.Fatal("mismatched TKEY data after rewriting bytes")
}
t.Logf("got TKEY of: " + rr.String())
// Now add some bytes to this and make sure we can encode OtherData properly
tkey := rr.(*TKEY)
tkey.OtherData = "abcd"
tkey.OtherLen = 2
offset, packErr = PackRR(tkey, msg, 0, nil, false)
if packErr != nil {
t.Fatal("unable to pack TKEY RR after modification", packErr)
}
if offset != (len(tkeyBytes) + 2) {
t.Fatalf("mismatched TKEY RR size %d != %d", offset, len(tkeyBytes)+2)
}
t.Logf("modified to TKEY of: " + rr.String())
// Make sure we can parse our string output
tkey.Hdr.Class = ClassINET // https://github.com/miekg/dns/issues/577
newRR, newError := NewRR(tkey.String())
if newError != nil {
t.Fatalf("unable to parse TKEY string: %s", newError)
}
t.Log("got reparsed TKEY of newRR: " + newRR.String())
}

80
vendor/github.com/miekg/dns/dnssec.go сгенерированный поставляемый
Просмотреть файл

@@ -19,6 +19,8 @@ import (
"sort"
"strings"
"time"
"golang.org/x/crypto/ed25519"
)
// DNSSEC encryption algorithm codes.
@@ -38,6 +40,8 @@ const (
ECCGOST
ECDSAP256SHA256
ECDSAP384SHA384
ED25519
ED448
INDIRECT uint8 = 252
PRIVATEDNS uint8 = 253 // Private (experimental keys)
PRIVATEOID uint8 = 254
@@ -56,6 +60,8 @@ var AlgorithmToString = map[uint8]string{
ECCGOST: "ECC-GOST",
ECDSAP256SHA256: "ECDSAP256SHA256",
ECDSAP384SHA384: "ECDSAP384SHA384",
ED25519: "ED25519",
ED448: "ED448",
INDIRECT: "INDIRECT",
PRIVATEDNS: "PRIVATEDNS",
PRIVATEOID: "PRIVATEOID",
@@ -73,6 +79,7 @@ var AlgorithmToHash = map[uint8]crypto.Hash{
ECDSAP256SHA256: crypto.SHA256,
ECDSAP384SHA384: crypto.SHA384,
RSASHA512: crypto.SHA512,
ED25519: crypto.Hash(0),
}
// DNSSEC hashing algorithm codes.
@@ -301,17 +308,33 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
return ErrAlg
}
h := hash.New()
h.Write(signdata)
h.Write(wire)
switch rr.Algorithm {
case ED25519:
// ed25519 signs the raw message and performs hashing internally.
// All other supported signature schemes operate over the pre-hashed
// message, and thus ed25519 must be handled separately here.
//
// The raw message is passed directly into sign and crypto.Hash(0) is
// used to signal to the crypto.Signer that the data has not been hashed.
signature, err := sign(k, append(signdata, wire...), crypto.Hash(0), rr.Algorithm)
if err != nil {
return err
}
signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
if err != nil {
return err
rr.Signature = toBase64(signature)
default:
h := hash.New()
h.Write(signdata)
h.Write(wire)
signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
if err != nil {
return err
}
rr.Signature = toBase64(signature)
}
rr.Signature = toBase64(signature)
return nil
}
@@ -352,6 +375,9 @@ func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte,
// signature = append(signature, intToBytes(r1, 20)...)
// signature = append(signature, intToBytes(s1, 20)...)
// rr.Signature = signature
case ED25519:
return signature, nil
}
return nil, ErrAlg
@@ -456,6 +482,17 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
}
return ErrSig
case ED25519:
pubkey := k.publicKeyED25519()
if pubkey == nil {
return ErrKey
}
if ed25519.Verify(pubkey, append(signeddata, wire...), sigbuf) {
return nil
}
return ErrSig
default:
return ErrAlg
}
@@ -578,6 +615,17 @@ func (k *DNSKEY) publicKeyDSA() *dsa.PublicKey {
return pubkey
}
func (k *DNSKEY) publicKeyED25519() ed25519.PublicKey {
keybuf, err := fromBase64([]byte(k.PublicKey))
if err != nil {
return nil
}
if len(keybuf) != ed25519.PublicKeySize {
return nil
}
return keybuf
}
type wireSlice [][]byte
func (p wireSlice) Len() int { return len(p) }
@@ -615,6 +663,10 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
switch x := r1.(type) {
case *NS:
x.Ns = strings.ToLower(x.Ns)
case *MD:
x.Md = strings.ToLower(x.Md)
case *MF:
x.Mf = strings.ToLower(x.Mf)
case *CNAME:
x.Target = strings.ToLower(x.Target)
case *SOA:
@@ -633,6 +685,18 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
x.Email = strings.ToLower(x.Email)
case *MX:
x.Mx = strings.ToLower(x.Mx)
case *RP:
x.Mbox = strings.ToLower(x.Mbox)
x.Txt = strings.ToLower(x.Txt)
case *AFSDB:
x.Hostname = strings.ToLower(x.Hostname)
case *RT:
x.Host = strings.ToLower(x.Host)
case *SIG:
x.SignerName = strings.ToLower(x.SignerName)
case *PX:
x.Map822 = strings.ToLower(x.Map822)
x.Mapx400 = strings.ToLower(x.Mapx400)
case *NAPTR:
x.Replacement = strings.ToLower(x.Replacement)
case *KX:

22
vendor/github.com/miekg/dns/dnssec_keygen.go сгенерированный поставляемый
Просмотреть файл

@@ -8,6 +8,8 @@ import (
"crypto/rand"
"crypto/rsa"
"math/big"
"golang.org/x/crypto/ed25519"
)
// Generate generates a DNSKEY of the given bit size.
@@ -38,6 +40,10 @@ func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
if bits != 384 {
return nil, ErrKeySize
}
case ED25519:
if bits != 256 {
return nil, ErrKeySize
}
}
switch k.Algorithm {
@@ -75,6 +81,13 @@ func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
}
k.setPublicKeyECDSA(priv.PublicKey.X, priv.PublicKey.Y)
return priv, nil
case ED25519:
pub, priv, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return nil, err
}
k.setPublicKeyED25519(pub)
return priv, nil
default:
return nil, ErrAlg
}
@@ -117,6 +130,15 @@ func (k *DNSKEY) setPublicKeyDSA(_Q, _P, _G, _Y *big.Int) bool {
return true
}
// Set the public key for Ed25519
func (k *DNSKEY) setPublicKeyED25519(_K ed25519.PublicKey) bool {
if _K == nil {
return false
}
k.PublicKey = toBase64(_K)
return true
}
// Set the public key (the values E and N) for RSA
// RFC 3110: Section 2. RSA Public KEY Resource Records
func exponentToBuf(_E int) []byte {

50
vendor/github.com/miekg/dns/dnssec_keyscan.go сгенерированный поставляемый
Просмотреть файл

@@ -1,6 +1,7 @@
package dns
import (
"bytes"
"crypto"
"crypto/dsa"
"crypto/ecdsa"
@@ -9,6 +10,8 @@ import (
"math/big"
"strconv"
"strings"
"golang.org/x/crypto/ed25519"
)
// NewPrivateKey returns a PrivateKey by parsing the string s.
@@ -86,6 +89,8 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
}
priv.PublicKey = *pub
return priv, nil
case ED25519:
return readPrivateKeyED25519(m)
default:
return nil, ErrPrivKey
}
@@ -166,13 +171,56 @@ func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) {
return p, nil
}
func readPrivateKeyED25519(m map[string]string) (ed25519.PrivateKey, error) {
var p ed25519.PrivateKey
// TODO: validate that the required flags are present
for k, v := range m {
switch k {
case "privatekey":
p1, err := fromBase64([]byte(v))
if err != nil {
return nil, err
}
if len(p1) != 32 {
return nil, ErrPrivKey
}
// RFC 8080 and Golang's x/crypto/ed25519 differ as to how the
// private keys are represented. RFC 8080 specifies that private
// keys be stored solely as the seed value (p1 above) while the
// ed25519 package represents them as the seed value concatenated
// to the public key, which is derived from the seed value.
//
// ed25519.GenerateKey reads exactly 32 bytes from the passed in
// io.Reader and uses them as the seed. It also derives the
// public key and produces a compatible private key.
_, p, err = ed25519.GenerateKey(bytes.NewReader(p1))
if err != nil {
return nil, err
}
case "created", "publish", "activate":
/* not used in Go (yet) */
}
}
return p, nil
}
// parseKey reads a private key from r. It returns a map[string]string,
// with the key-value pairs, or an error when the file is not correct.
func parseKey(r io.Reader, file string) (map[string]string, error) {
s := scanInit(r)
s, cancel := scanInit(r)
m := make(map[string]string)
c := make(chan lex)
k := ""
defer func() {
cancel()
// zlexer can send up to two tokens, the next one and possibly 1 remainders.
// Do a non-blocking read.
_, ok := <-c
_, ok = <-c
if !ok {
// too bad
}
}()
// Start the lexer
go klexer(s, c)
for l := range c {

8
vendor/github.com/miekg/dns/dnssec_privkey.go сгенерированный поставляемый
Просмотреть файл

@@ -7,6 +7,8 @@ import (
"crypto/rsa"
"math/big"
"strconv"
"golang.org/x/crypto/ed25519"
)
const format = "Private-key-format: v1.3\n"
@@ -79,6 +81,12 @@ func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
"Private_value(x): " + priv + "\n" +
"Public_value(y): " + pub + "\n"
case ed25519.PrivateKey:
private := toBase64(p[:32])
return format +
"Algorithm: " + algorithm + "\n" +
"PrivateKey: " + private + "\n"
default:
return ""
}

189
vendor/github.com/miekg/dns/dnssec_test.go сгенерированный поставляемый
Просмотреть файл

@@ -8,6 +8,8 @@ import (
"strings"
"testing"
"time"
"golang.org/x/crypto/ed25519"
)
func getKey() *DNSKEY {
@@ -461,6 +463,55 @@ func TestSignVerifyECDSA2(t *testing.T) {
}
}
func TestSignVerifyEd25519(t *testing.T) {
srv1, err := NewRR("srv.miek.nl. IN SRV 1000 800 0 web1.miek.nl.")
if err != nil {
t.Fatal(err)
}
srv := srv1.(*SRV)
// With this key
key := new(DNSKEY)
key.Hdr.Rrtype = TypeDNSKEY
key.Hdr.Name = "miek.nl."
key.Hdr.Class = ClassINET
key.Hdr.Ttl = 14400
key.Flags = 256
key.Protocol = 3
key.Algorithm = ED25519
privkey, err := key.Generate(256)
if err != nil {
t.Fatal("failure to generate key")
}
// Fill in the values of the Sig, before signing
sig := new(RRSIG)
sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0}
sig.TypeCovered = srv.Hdr.Rrtype
sig.Labels = uint8(CountLabel(srv.Hdr.Name)) // works for all 3
sig.OrigTtl = srv.Hdr.Ttl
sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05"
sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05"
sig.KeyTag = key.KeyTag() // Get the keyfrom the Key
sig.SignerName = key.Hdr.Name
sig.Algorithm = ED25519
if sig.Sign(privkey.(ed25519.PrivateKey), []RR{srv}) != nil {
t.Fatal("failure to sign the record")
}
err = sig.Verify(key, []RR{srv})
if err != nil {
t.Logf("failure to validate:\n%s\n%s\n%s\n\n%s\n\n%v",
key.String(),
srv.String(),
sig.String(),
key.PrivateKeyString(privkey),
err,
)
}
}
// Here the test vectors from the relevant RFCs are checked.
// rfc6605 6.1
func TestRFC6605P256(t *testing.T) {
@@ -590,6 +641,144 @@ PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR`
}
}
// rfc8080 6.1
func TestRFC8080Ed25519Example1(t *testing.T) {
exDNSKEY := `example.com. 3600 IN DNSKEY 257 3 15 (
l02Woi0iS8Aa25FQkUd9RMzZHJpBoRQwAQEX1SxZJA4= )`
exPriv := `Private-key-format: v1.2
Algorithm: 15 (ED25519)
PrivateKey: ODIyNjAzODQ2MjgwODAxMjI2NDUxOTAyMDQxNDIyNjI=`
rrDNSKEY, err := NewRR(exDNSKEY)
if err != nil {
t.Fatal(err)
}
priv, err := rrDNSKEY.(*DNSKEY).NewPrivateKey(exPriv)
if err != nil {
t.Fatal(err)
}
exDS := `example.com. 3600 IN DS 3613 15 2 (
3aa5ab37efce57f737fc1627013fee07bdf241bd10f3b1964ab55c78e79
a304b )`
rrDS, err := NewRR(exDS)
if err != nil {
t.Fatal(err)
}
ourDS := rrDNSKEY.(*DNSKEY).ToDS(SHA256)
if !reflect.DeepEqual(ourDS, rrDS.(*DS)) {
t.Fatalf("DS record differs:\n%v\n%v", ourDS, rrDS.(*DS))
}
exMX := `example.com. 3600 IN MX 10 mail.example.com.`
exRRSIG := `example.com. 3600 IN RRSIG MX 15 2 3600 (
1440021600 1438207200 3613 example.com. (
oL9krJun7xfBOIWcGHi7mag5/hdZrKWw15jPGrHpjQeRAvTdszaPD+QLs3f
x8A4M3e23mRZ9VrbpMngwcrqNAg== ) )`
rrMX, err := NewRR(exMX)
if err != nil {
t.Fatal(err)
}
rrRRSIG, err := NewRR(exRRSIG)
if err != nil {
t.Fatal(err)
}
if err = rrRRSIG.(*RRSIG).Verify(rrDNSKEY.(*DNSKEY), []RR{rrMX}); err != nil {
t.Errorf("failure to validate the spec RRSIG: %v", err)
}
ourRRSIG := &RRSIG{
Hdr: RR_Header{
Ttl: rrMX.Header().Ttl,
},
KeyTag: rrDNSKEY.(*DNSKEY).KeyTag(),
SignerName: rrDNSKEY.(*DNSKEY).Hdr.Name,
Algorithm: rrDNSKEY.(*DNSKEY).Algorithm,
}
ourRRSIG.Expiration, _ = StringToTime("20150819220000")
ourRRSIG.Inception, _ = StringToTime("20150729220000")
err = ourRRSIG.Sign(priv.(ed25519.PrivateKey), []RR{rrMX})
if err != nil {
t.Fatal(err)
}
if err = ourRRSIG.Verify(rrDNSKEY.(*DNSKEY), []RR{rrMX}); err != nil {
t.Errorf("failure to validate our RRSIG: %v", err)
}
if !reflect.DeepEqual(ourRRSIG, rrRRSIG.(*RRSIG)) {
t.Fatalf("RRSIG record differs:\n%v\n%v", ourRRSIG, rrRRSIG.(*RRSIG))
}
}
// rfc8080 6.1
func TestRFC8080Ed25519Example2(t *testing.T) {
exDNSKEY := `example.com. 3600 IN DNSKEY 257 3 15 (
zPnZ/QwEe7S8C5SPz2OfS5RR40ATk2/rYnE9xHIEijs= )`
exPriv := `Private-key-format: v1.2
Algorithm: 15 (ED25519)
PrivateKey: DSSF3o0s0f+ElWzj9E/Osxw8hLpk55chkmx0LYN5WiY=`
rrDNSKEY, err := NewRR(exDNSKEY)
if err != nil {
t.Fatal(err)
}
priv, err := rrDNSKEY.(*DNSKEY).NewPrivateKey(exPriv)
if err != nil {
t.Fatal(err)
}
exDS := `example.com. 3600 IN DS 35217 15 2 (
401781b934e392de492ec77ae2e15d70f6575a1c0bc59c5275c04ebe80c
6614c )`
rrDS, err := NewRR(exDS)
if err != nil {
t.Fatal(err)
}
ourDS := rrDNSKEY.(*DNSKEY).ToDS(SHA256)
if !reflect.DeepEqual(ourDS, rrDS.(*DS)) {
t.Fatalf("DS record differs:\n%v\n%v", ourDS, rrDS.(*DS))
}
exMX := `example.com. 3600 IN MX 10 mail.example.com.`
exRRSIG := `example.com. 3600 IN RRSIG MX 15 2 3600 (
1440021600 1438207200 35217 example.com. (
zXQ0bkYgQTEFyfLyi9QoiY6D8ZdYo4wyUhVioYZXFdT410QPRITQSqJSnzQ
oSm5poJ7gD7AQR0O7KuI5k2pcBg== ) )`
rrMX, err := NewRR(exMX)
if err != nil {
t.Fatal(err)
}
rrRRSIG, err := NewRR(exRRSIG)
if err != nil {
t.Fatal(err)
}
if err = rrRRSIG.(*RRSIG).Verify(rrDNSKEY.(*DNSKEY), []RR{rrMX}); err != nil {
t.Errorf("failure to validate the spec RRSIG: %v", err)
}
ourRRSIG := &RRSIG{
Hdr: RR_Header{
Ttl: rrMX.Header().Ttl,
},
KeyTag: rrDNSKEY.(*DNSKEY).KeyTag(),
SignerName: rrDNSKEY.(*DNSKEY).Hdr.Name,
Algorithm: rrDNSKEY.(*DNSKEY).Algorithm,
}
ourRRSIG.Expiration, _ = StringToTime("20150819220000")
ourRRSIG.Inception, _ = StringToTime("20150729220000")
err = ourRRSIG.Sign(priv.(ed25519.PrivateKey), []RR{rrMX})
if err != nil {
t.Fatal(err)
}
if err = ourRRSIG.Verify(rrDNSKEY.(*DNSKEY), []RR{rrMX}); err != nil {
t.Errorf("failure to validate our RRSIG: %v", err)
}
if !reflect.DeepEqual(ourRRSIG, rrRRSIG.(*RRSIG)) {
t.Fatalf("RRSIG record differs:\n%v\n%v", ourRRSIG, rrRRSIG.(*RRSIG))
}
}
func TestInvalidRRSet(t *testing.T) {
goodRecords := make([]RR, 2)
goodRecords[0] = &TXT{Hdr: RR_Header{Name: "name.cloudflare.com.", Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}}

2
vendor/github.com/miekg/dns/doc.go сгенерированный поставляемый
Просмотреть файл

@@ -63,7 +63,7 @@ class) is as easy as setting:
c.SingleInflight = true
More advanced options are availabe using a net.Dialer and the corresponding API.
More advanced options are available using a net.Dialer and the corresponding API.
For example it is possible to set a timeout, or to specify a source IP address
and port to use for the connection:

39
vendor/github.com/miekg/dns/edns.go сгенерированный поставляемый
Просмотреть файл

@@ -13,19 +13,18 @@ import (
const (
EDNS0LLQ = 0x1 // long lived queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
EDNS0UL = 0x2 // update lease draft: http://files.dns-sd.org/draft-sekar-dns-ul.txt
EDNS0NSID = 0x3 // nsid (RFC5001)
EDNS0NSID = 0x3 // nsid (See RFC 5001)
EDNS0DAU = 0x5 // DNSSEC Algorithm Understood
EDNS0DHU = 0x6 // DS Hash Understood
EDNS0N3U = 0x7 // NSEC3 Hash Understood
EDNS0SUBNET = 0x8 // client-subnet (RFC6891)
EDNS0SUBNET = 0x8 // client-subnet (See RFC 7871)
EDNS0EXPIRE = 0x9 // EDNS0 expire
EDNS0COOKIE = 0xa // EDNS0 Cookie
EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (RFC7828)
EDNS0PADDING = 0xc // EDNS0 padding (RFC7830)
EDNS0SUBNETDRAFT = 0x50fa // Don't use! Use EDNS0SUBNET
EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (RFC6891)
EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (RFC6891)
_DO = 1 << 15 // dnssec ok
EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (See RFC 7828)
EDNS0PADDING = 0xc // EDNS0 padding (See RFC 7830)
EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (See RFC 6891)
EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (See RFC 6891)
_DO = 1 << 15 // DNSSEC OK
)
// OPT is the EDNS0 RR appended to messages to convey extra (meta) information.
@@ -58,9 +57,6 @@ func (rr *OPT) String() string {
}
case *EDNS0_SUBNET:
s += "\n; SUBNET: " + o.String()
if o.(*EDNS0_SUBNET).DraftOption {
s += " (draft)"
}
case *EDNS0_COOKIE:
s += "\n; COOKIE: " + o.String()
case *EDNS0_UL:
@@ -188,7 +184,7 @@ func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); re
func (e *EDNS0_NSID) String() string { return string(e.Nsid) }
// EDNS0_SUBNET is the subnet option that is used to give the remote nameserver
// an idea of where the client lives. It can then give back a different
// an idea of where the client lives. See RFC 7871. It can then give back a different
// answer depending on the location or network topology.
// Basic use pattern for creating an subnet option:
//
@@ -204,26 +200,19 @@ func (e *EDNS0_NSID) String() string { return string(e.Nsid) }
// // e.Address = net.ParseIP("2001:7b8:32a::2") // for IPV6
// o.Option = append(o.Option, e)
//
// Note: the spec (draft-ietf-dnsop-edns-client-subnet-00) has some insane logic
// for which netmask applies to the address. This code will parse all the
// available bits when unpacking (up to optlen). When packing it will apply
// SourceNetmask. If you need more advanced logic, patches welcome and good luck.
// This code will parse all the available bits when unpacking (up to optlen).
// When packing it will apply SourceNetmask. If you need more advanced logic,
// patches welcome and good luck.
type EDNS0_SUBNET struct {
Code uint16 // Always EDNS0SUBNET
Family uint16 // 1 for IP, 2 for IP6
SourceNetmask uint8
SourceScope uint8
Address net.IP
DraftOption bool // Set to true if using the old (0x50fa) option code
}
// Option implements the EDNS0 interface.
func (e *EDNS0_SUBNET) Option() uint16 {
if e.DraftOption {
return EDNS0SUBNETDRAFT
}
return EDNS0SUBNET
}
func (e *EDNS0_SUBNET) Option() uint16 { return EDNS0SUBNET }
func (e *EDNS0_SUBNET) pack() ([]byte, error) {
b := make([]byte, 4)
@@ -431,6 +420,7 @@ func (e *EDNS0_LLQ) String() string {
return s
}
// EDNS0_DUA implements the EDNS0 "DNSSEC Algorithm Understood" option. See RFC 6975.
type EDNS0_DAU struct {
Code uint16 // Always EDNS0DAU
AlgCode []uint8
@@ -453,6 +443,7 @@ func (e *EDNS0_DAU) String() string {
return s
}
// EDNS0_DHU implements the EDNS0 "DS Hash Understood" option. See RFC 6975.
type EDNS0_DHU struct {
Code uint16 // Always EDNS0DHU
AlgCode []uint8
@@ -475,6 +466,7 @@ func (e *EDNS0_DHU) String() string {
return s
}
// EDNS0_N3U implements the EDNS0 "NSEC3 Hash Understood" option. See RFC 6975.
type EDNS0_N3U struct {
Code uint16 // Always EDNS0N3U
AlgCode []uint8
@@ -498,6 +490,7 @@ func (e *EDNS0_N3U) String() string {
return s
}
// EDNS0_EXPIRE implementes the EDNS0 option as described in RFC 7314.
type EDNS0_EXPIRE struct {
Code uint16 // Always EDNS0EXPIRE
Expire uint32

23
vendor/github.com/miekg/dns/fuzz.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,23 @@
// +build fuzz
package dns
func Fuzz(data []byte) int {
msg := new(Msg)
if err := msg.Unpack(data); err != nil {
return 0
}
if _, err := msg.Pack(); err != nil {
return 0
}
return 1
}
func FuzzNewRR(data []byte) int {
if _, err := NewRR(string(data)); err != nil {
return 0
}
return 1
}

25
vendor/github.com/miekg/dns/fuzz_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,25 +0,0 @@
package dns
import "testing"
func TestFuzzString(t *testing.T) {
testcases := []string{"", " MINFO ", " RP ", " NSEC 0 0", " \" NSEC 0 0\"", " \" MINFO \"",
";a ", ";a<><61><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
" NSAP O ", " NSAP N ",
" TYPE4 TYPE6a789a3bc0045c8a5fb42c7d1bd998f5444 IN 9579b47d46817afbd17273e6",
" TYPE45 3 3 4147994 TYPE\\(\\)\\)\\(\\)\\(\\(\\)\\(\\)\\)\\)\\(\\)\\(\\)\\(\\(\\R 948\"\")\\(\\)\\)\\)\\(\\ ",
"$GENERATE 0-3 ${441189,5039418474430,o}",
"$INCLUDE 00 TYPE00000000000n ",
"$INCLUDE PE4 TYPE061463623/727071511 \\(\\)\\$GENERATE 6-462/0",
}
for i, tc := range testcases {
rr, err := NewRR(tc)
if err == nil {
// rr can be nil because we can (for instance) just parse a comment
if rr == nil {
continue
}
t.Fatalf("parsed mailformed RR %d: %s", i, rr.String())
}
}
}

2346
vendor/github.com/miekg/dns/idn/code_points.go сгенерированный поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

18
vendor/github.com/miekg/dns/idn/example_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,18 +0,0 @@
package idn_test
import (
"fmt"
"github.com/miekg/dns/idn"
)
func ExampleToPunycode() {
name := "インターネット.テスト"
fmt.Printf("%s -> %s", name, idn.ToPunycode(name))
// Output: インターネット.テスト -> xn--eckucmux0ukc.xn--zckzah
}
func ExampleFromPunycode() {
name := "xn--mgbaja8a1hpac.xn--mgbachtv"
fmt.Printf("%s -> %s", name, idn.FromPunycode(name))
// Output: xn--mgbaja8a1hpac.xn--mgbachtv -> الانترنت.اختبار
}

370
vendor/github.com/miekg/dns/idn/punycode.go сгенерированный поставляемый
Просмотреть файл

@@ -1,370 +0,0 @@
// Package idn implements encoding from and to punycode as speficied by RFC 3492.
package idn
import (
"bytes"
"strings"
"unicode"
"unicode/utf8"
"github.com/miekg/dns"
)
// Implementation idea from RFC itself and from from IDNA::Punycode created by
// Tatsuhiko Miyagawa <miyagawa@bulknews.net> and released under Perl Artistic
// License in 2002.
const (
_MIN rune = 1
_MAX rune = 26
_SKEW rune = 38
_BASE rune = 36
_BIAS rune = 72
_N rune = 128
_DAMP rune = 700
_DELIMITER = '-'
_PREFIX = "xn--"
)
// ToPunycode converts unicode domain names to DNS-appropriate punycode names.
// This function will return an empty string result for domain names with
// invalid unicode strings. This function expects domain names in lowercase.
func ToPunycode(s string) string {
// Early check to see if encoding is needed.
// This will prevent making heap allocations when not needed.
if !needToPunycode(s) {
return s
}
tokens := dns.SplitDomainName(s)
switch {
case s == "":
return ""
case tokens == nil: // s == .
return "."
case s[len(s)-1] == '.':
tokens = append(tokens, "")
}
for i := range tokens {
t := encode([]byte(tokens[i]))
if t == nil {
return ""
}
tokens[i] = string(t)
}
return strings.Join(tokens, ".")
}
// FromPunycode returns unicode domain name from provided punycode string.
// This function expects punycode strings in lowercase.
func FromPunycode(s string) string {
// Early check to see if decoding is needed.
// This will prevent making heap allocations when not needed.
if !needFromPunycode(s) {
return s
}
tokens := dns.SplitDomainName(s)
switch {
case s == "":
return ""
case tokens == nil: // s == .
return "."
case s[len(s)-1] == '.':
tokens = append(tokens, "")
}
for i := range tokens {
tokens[i] = string(decode([]byte(tokens[i])))
}
return strings.Join(tokens, ".")
}
// digitval converts single byte into meaningful value that's used to calculate decoded unicode character.
const errdigit = 0xffff
func digitval(code rune) rune {
switch {
case code >= 'A' && code <= 'Z':
return code - 'A'
case code >= 'a' && code <= 'z':
return code - 'a'
case code >= '0' && code <= '9':
return code - '0' + 26
}
return errdigit
}
// lettercode finds BASE36 byte (a-z0-9) based on calculated number.
func lettercode(digit rune) rune {
switch {
case digit >= 0 && digit <= 25:
return digit + 'a'
case digit >= 26 && digit <= 36:
return digit - 26 + '0'
}
panic("dns: not reached")
}
// adapt calculates next bias to be used for next iteration delta.
func adapt(delta rune, numpoints int, firsttime bool) rune {
if firsttime {
delta /= _DAMP
} else {
delta /= 2
}
var k rune
for delta = delta + delta/rune(numpoints); delta > (_BASE-_MIN)*_MAX/2; k += _BASE {
delta /= _BASE - _MIN
}
return k + ((_BASE-_MIN+1)*delta)/(delta+_SKEW)
}
// next finds minimal rune (one with lowest codepoint value) that should be equal or above boundary.
func next(b []rune, boundary rune) rune {
if len(b) == 0 {
panic("dns: invalid set of runes to determine next one")
}
m := b[0]
for _, x := range b[1:] {
if x >= boundary && (m < boundary || x < m) {
m = x
}
}
return m
}
// preprune converts unicode rune to lower case. At this time it's not
// supporting all things described in RFCs.
func preprune(r rune) rune {
if unicode.IsUpper(r) {
r = unicode.ToLower(r)
}
return r
}
// tfunc is a function that helps calculate each character weight.
func tfunc(k, bias rune) rune {
switch {
case k <= bias:
return _MIN
case k >= bias+_MAX:
return _MAX
}
return k - bias
}
// needToPunycode returns true for strings that require punycode encoding
// (contain unicode characters).
func needToPunycode(s string) bool {
// This function is very similar to bytes.Runes. We don't use bytes.Runes
// because it makes a heap allocation that's not needed here.
for i := 0; len(s) > 0; i++ {
r, l := utf8.DecodeRuneInString(s)
if r > 0x7f {
return true
}
s = s[l:]
}
return false
}
// needFromPunycode returns true for strings that require punycode decoding.
func needFromPunycode(s string) bool {
if s == "." {
return false
}
off := 0
end := false
pl := len(_PREFIX)
sl := len(s)
// If s starts with _PREFIX.
if sl > pl && s[off:off+pl] == _PREFIX {
return true
}
for {
// Find the part after the next ".".
off, end = dns.NextLabel(s, off)
if end {
return false
}
// If this parts starts with _PREFIX.
if sl-off > pl && s[off:off+pl] == _PREFIX {
return true
}
}
}
// encode transforms Unicode input bytes (that represent DNS label) into
// punycode bytestream. This function would return nil if there's an invalid
// character in the label.
func encode(input []byte) []byte {
n, bias := _N, _BIAS
b := bytes.Runes(input)
for i := range b {
if !isValidRune(b[i]) {
return nil
}
b[i] = preprune(b[i])
}
basic := make([]byte, 0, len(b))
for _, ltr := range b {
if ltr <= 0x7f {
basic = append(basic, byte(ltr))
}
}
basiclen := len(basic)
fulllen := len(b)
if basiclen == fulllen {
return basic
}
var out bytes.Buffer
out.WriteString(_PREFIX)
if basiclen > 0 {
out.Write(basic)
out.WriteByte(_DELIMITER)
}
var (
ltr, nextltr rune
delta, q rune // delta calculation (see rfc)
t, k, cp rune // weight and codepoint calculation
)
for h := basiclen; h < fulllen; n, delta = n+1, delta+1 {
nextltr = next(b, n)
delta, n = delta+(nextltr-n)*rune(h+1), nextltr
for _, ltr = range b {
if ltr < n {
delta++
}
if ltr == n {
q = delta
for k = _BASE; ; k += _BASE {
t = tfunc(k, bias)
if q < t {
break
}
cp = t + ((q - t) % (_BASE - t))
out.WriteRune(lettercode(cp))
q = (q - t) / (_BASE - t)
}
out.WriteRune(lettercode(q))
bias = adapt(delta, h+1, h == basiclen)
h, delta = h+1, 0
}
}
}
return out.Bytes()
}
// decode transforms punycode input bytes (that represent DNS label) into Unicode bytestream.
func decode(b []byte) []byte {
src := b // b would move and we need to keep it
n, bias := _N, _BIAS
if !bytes.HasPrefix(b, []byte(_PREFIX)) {
return b
}
out := make([]rune, 0, len(b))
b = b[len(_PREFIX):]
for pos := len(b) - 1; pos >= 0; pos-- {
// only last delimiter is our interest
if b[pos] == _DELIMITER {
out = append(out, bytes.Runes(b[:pos])...)
b = b[pos+1:] // trim source string
break
}
}
if len(b) == 0 {
return src
}
var (
i, oldi, w rune
ch byte
t, digit rune
ln int
)
for i = 0; len(b) > 0; i++ {
oldi, w = i, 1
for k := _BASE; len(b) > 0; k += _BASE {
ch, b = b[0], b[1:]
digit = digitval(rune(ch))
if digit == errdigit {
return src
}
i += digit * w
if i < 0 {
// safety check for rune overflow
return src
}
t = tfunc(k, bias)
if digit < t {
break
}
w *= _BASE - t
}
ln = len(out) + 1
bias = adapt(i-oldi, ln, oldi == 0)
n += i / rune(ln)
i = i % rune(ln)
// insert
out = append(out, 0)
copy(out[i+1:], out[i:])
out[i] = n
}
var ret bytes.Buffer
for _, r := range out {
ret.WriteRune(r)
}
return ret.Bytes()
}
// isValidRune checks if the character is valid. We will look for the
// character property in the code points list. For now we aren't checking special
// rules in case of contextual property
func isValidRune(r rune) bool {
return findProperty(r) == propertyPVALID
}
// findProperty will try to check the code point property of the given
// character. It will use a binary search algorithm as we have a slice of
// ordered ranges (average case performance O(log n))
func findProperty(r rune) property {
imin, imax := 0, len(codePoints)
for imax >= imin {
imid := (imin + imax) / 2
codePoint := codePoints[imid]
if (codePoint.start == r && codePoint.end == 0) || (codePoint.start <= r && codePoint.end >= r) {
return codePoint.state
}
if (codePoint.end > 0 && codePoint.end < r) || (codePoint.end == 0 && codePoint.start < r) {
imin = imid + 1
} else {
imax = imid - 1
}
}
return propertyUnknown
}

116
vendor/github.com/miekg/dns/idn/punycode_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,116 +0,0 @@
package idn
import (
"strings"
"testing"
)
var testcases = [][2]string{
{"", ""},
{"a", "a"},
{"a-b", "a-b"},
{"a-b-c", "a-b-c"},
{"abc", "abc"},
{"я", "xn--41a"},
{"zя", "xn--z-0ub"},
{"яZ", "xn--z-zub"},
{"а-я", "xn----7sb8g"},
{"إختبار", "xn--kgbechtv"},
{"آزمایشی", "xn--hgbk6aj7f53bba"},
{"测试", "xn--0zwm56d"},
{"測試", "xn--g6w251d"},
{"испытание", "xn--80akhbyknj4f"},
{"परीक्षा", "xn--11b5bs3a9aj6g"},
{"δοκιμή", "xn--jxalpdlp"},
{"테스트", "xn--9t4b11yi5a"},
{"טעסט", "xn--deba0ad"},
{"テスト", "xn--zckzah"},
{"பரிட்சை", "xn--hlcj6aya9esc7a"},
{"mamão-com-açúcar", "xn--mamo-com-acar-yeb1e6q"},
{"σ", "xn--4xa"},
}
func TestEncodeDecodePunycode(t *testing.T) {
for _, tst := range testcases {
enc := encode([]byte(tst[0]))
if string(enc) != tst[1] {
t.Errorf("%s encodeded as %s but should be %s", tst[0], enc, tst[1])
}
dec := decode([]byte(tst[1]))
if string(dec) != strings.ToLower(tst[0]) {
t.Errorf("%s decoded as %s but should be %s", tst[1], dec, strings.ToLower(tst[0]))
}
}
}
func TestToFromPunycode(t *testing.T) {
for _, tst := range testcases {
// assert unicode.com == punycode.com
full := ToPunycode(tst[0] + ".com")
if full != tst[1]+".com" {
t.Errorf("invalid result from string conversion to punycode, %s and should be %s.com", full, tst[1])
}
// assert punycode.punycode == unicode.unicode
decoded := FromPunycode(tst[1] + "." + tst[1])
if decoded != strings.ToLower(tst[0]+"."+tst[0]) {
t.Errorf("invalid result from string conversion to punycode, %s and should be %s.%s", decoded, tst[0], tst[0])
}
}
}
func TestEncodeDecodeFinalPeriod(t *testing.T) {
for _, tst := range testcases {
// assert unicode.com. == punycode.com.
full := ToPunycode(tst[0] + ".")
if full != tst[1]+"." {
t.Errorf("invalid result from string conversion to punycode when period added at the end, %#v and should be %#v", full, tst[1]+".")
}
// assert punycode.com. == unicode.com.
decoded := FromPunycode(tst[1] + ".")
if decoded != strings.ToLower(tst[0]+".") {
t.Errorf("invalid result from string conversion to punycode when period added, %#v and should be %#v", decoded, tst[0]+".")
}
full = ToPunycode(tst[0])
if full != tst[1] {
t.Errorf("invalid result from string conversion to punycode when no period added at the end, %#v and should be %#v", full, tst[1]+".")
}
// assert punycode.com. == unicode.com.
decoded = FromPunycode(tst[1])
if decoded != strings.ToLower(tst[0]) {
t.Errorf("invalid result from string conversion to punycode when no period added, %#v and should be %#v", decoded, tst[0]+".")
}
}
}
var invalidACEs = []string{
"xn--*",
"xn--",
"xn---",
"xn--a000000000",
}
func TestInvalidPunycode(t *testing.T) {
for _, d := range invalidACEs {
s := FromPunycode(d)
if s != d {
t.Errorf("Changed invalid name %s to %#v", d, s)
}
}
}
// You can verify the labels that are valid or not comparing to the Verisign
// website: http://mct.verisign-grs.com/
var invalidUnicodes = []string{
"Σ",
"ЯZ",
"Испытание",
}
func TestInvalidUnicodes(t *testing.T) {
for _, d := range invalidUnicodes {
s := ToPunycode(d)
if s != "" {
t.Errorf("Changed invalid name %s to %#v", d, s)
}
}
}

7
vendor/github.com/miekg/dns/internal/socket/cmsghdr.go сгенерированный поставляемый
Просмотреть файл

@@ -1,7 +0,0 @@
// +build linux
package socket
func (h *cmsghdr) len() int { return int(h.Len) }
func (h *cmsghdr) lvl() int { return int(h.Level) }
func (h *cmsghdr) typ() int { return int(h.Type) }

118
vendor/github.com/miekg/dns/internal/socket/controlmessage.go сгенерированный поставляемый
Просмотреть файл

@@ -1,118 +0,0 @@
package socket
import (
"errors"
"unsafe"
)
func controlHeaderLen() int {
return roundup(sizeofCmsghdr)
}
func controlMessageLen(dataLen int) int {
return roundup(sizeofCmsghdr) + dataLen
}
// returns the whole length of control message.
func ControlMessageSpace(dataLen int) int {
return roundup(sizeofCmsghdr) + roundup(dataLen)
}
// A ControlMessage represents the head message in a stream of control
// messages.
//
// A control message comprises of a header, data and a few padding
// fields to conform to the interface to the kernel.
//
// See RFC 3542 for further information.
type ControlMessage []byte
// Data returns the data field of the control message at the head.
func (m ControlMessage) Data(dataLen int) []byte {
l := controlHeaderLen()
if len(m) < l || len(m) < l+dataLen {
return nil
}
return m[l : l+dataLen]
}
// ParseHeader parses and returns the header fields of the control
// message at the head.
func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
l := controlHeaderLen()
if len(m) < l {
return 0, 0, 0, errors.New("short message")
}
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil
}
// Next returns the control message at the next.
func (m ControlMessage) Next(dataLen int) ControlMessage {
l := ControlMessageSpace(dataLen)
if len(m) < l {
return nil
}
return m[l:]
}
// MarshalHeader marshals the header fields of the control message at
// the head.
func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
if len(m) < controlHeaderLen() {
return errors.New("short message")
}
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
h.set(controlMessageLen(dataLen), lvl, typ)
return nil
}
// Marshal marshals the control message at the head, and returns the next
// control message.
func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
l := len(data)
if len(m) < ControlMessageSpace(l) {
return nil, errors.New("short message")
}
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
h.set(controlMessageLen(l), lvl, typ)
if l > 0 {
copy(m.Data(l), data)
}
return m.Next(l), nil
}
// Parse parses as a single or multiple control messages.
func (m ControlMessage) Parse() ([]ControlMessage, error) {
var ms []ControlMessage
for len(m) >= controlHeaderLen() {
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
l := h.len()
if l <= 0 {
return nil, errors.New("invalid header length")
}
if uint64(l) < uint64(controlHeaderLen()) {
return nil, errors.New("invalid message length")
}
if uint64(l) > uint64(len(m)) {
return nil, errors.New("short buffer")
}
ms = append(ms, ControlMessage(m[:l]))
ll := l - controlHeaderLen()
if len(m) >= ControlMessageSpace(ll) {
m = m[ControlMessageSpace(ll):]
} else {
m = m[controlMessageLen(ll):]
}
}
return ms, nil
}
// NewControlMessage returns a new stream of control messages.
func NewControlMessage(dataLen []int) ControlMessage {
var l int
for i := range dataLen {
l += ControlMessageSpace(dataLen[i])
}
return make([]byte, l)
}

103
vendor/github.com/miekg/dns/internal/socket/controlmessage_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,103 +0,0 @@
// +build linux
package socket
import (
"bytes"
"testing"
)
type mockControl struct {
Level int
Type int
Data []byte
}
func TestControlMessage(t *testing.T) {
for _, tt := range []struct {
cs []mockControl
}{
{
[]mockControl{
{Level: 1, Type: 1},
},
},
{
[]mockControl{
{Level: 2, Type: 2, Data: []byte{0xfe}},
},
},
{
[]mockControl{
{Level: 3, Type: 3, Data: []byte{0xfe, 0xff, 0xff, 0xfe}},
},
},
{
[]mockControl{
{Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
},
},
{
[]mockControl{
{Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
{Level: 2, Type: 2, Data: []byte{0xfe}},
},
},
} {
var w []byte
var tailPadLen int
mm := NewControlMessage([]int{0})
for i, c := range tt.cs {
m := NewControlMessage([]int{len(c.Data)})
l := len(m) - len(mm)
if i == len(tt.cs)-1 && l > len(c.Data) {
tailPadLen = l - len(c.Data)
}
w = append(w, m...)
}
var err error
ww := make([]byte, len(w))
copy(ww, w)
m := ControlMessage(ww)
for _, c := range tt.cs {
if err = m.MarshalHeader(c.Level, c.Type, len(c.Data)); err != nil {
t.Fatalf("(%v).MarshalHeader() = %v", tt.cs, err)
}
copy(m.Data(len(c.Data)), c.Data)
m = m.Next(len(c.Data))
}
m = ControlMessage(w)
for _, c := range tt.cs {
m, err = m.Marshal(c.Level, c.Type, c.Data)
if err != nil {
t.Fatalf("(%v).Marshal() = %v", tt.cs, err)
}
}
if !bytes.Equal(ww, w) {
t.Fatalf("got %#v; want %#v", ww, w)
}
ws := [][]byte{w}
if tailPadLen > 0 {
// Test a message with no tail padding.
nopad := w[:len(w)-tailPadLen]
ws = append(ws, [][]byte{nopad}...)
}
for _, w := range ws {
ms, err := ControlMessage(w).Parse()
if err != nil {
t.Fatalf("(%v).Parse() = %v", tt.cs, err)
}
for i, m := range ms {
lvl, typ, dataLen, err := m.ParseHeader()
if err != nil {
t.Fatalf("(%v).ParseHeader() = %v", tt.cs, err)
}
if lvl != tt.cs[i].Level || typ != tt.cs[i].Type || dataLen != len(tt.cs[i].Data) {
t.Fatalf("%v: got %d, %d, %d; want %d, %d, %d", tt.cs[i], lvl, typ, dataLen, tt.cs[i].Level, tt.cs[i].Type, len(tt.cs[i].Data))
}
}
}
}
}

4
vendor/github.com/miekg/dns/internal/socket/socket.go сгенерированный поставляемый
Просмотреть файл

@@ -1,4 +0,0 @@
// Package socket contains ControlMessage parsing code from
// golang.org/x/net/internal/socket. Instead of supporting all possible
// architectures, we're only supporting linux 32/64 bit.
package socket

14
vendor/github.com/miekg/dns/internal/socket/sys.go сгенерированный поставляемый
Просмотреть файл

@@ -1,14 +0,0 @@
package socket
import "unsafe"
var (
kernelAlign = func() int {
var p uintptr
return int(unsafe.Sizeof(p))
}()
)
func roundup(l int) int {
return (l + kernelAlign - 1) & ^(kernelAlign - 1)
}

71
vendor/github.com/miekg/dns/leak_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,71 @@
package dns
import (
"fmt"
"os"
"runtime"
"sort"
"strings"
"testing"
"time"
)
// copied from net/http/main_test.go
func interestingGoroutines() (gs []string) {
buf := make([]byte, 2<<20)
buf = buf[:runtime.Stack(buf, true)]
for _, g := range strings.Split(string(buf), "\n\n") {
sl := strings.SplitN(g, "\n", 2)
if len(sl) != 2 {
continue
}
stack := strings.TrimSpace(sl[1])
if stack == "" ||
strings.Contains(stack, "testing.(*M).before.func1") ||
strings.Contains(stack, "os/signal.signal_recv") ||
strings.Contains(stack, "created by net.startServer") ||
strings.Contains(stack, "created by testing.RunTests") ||
strings.Contains(stack, "closeWriteAndWait") ||
strings.Contains(stack, "testing.Main(") ||
strings.Contains(stack, "testing.(*T).Run(") ||
// These only show up with GOTRACEBACK=2; Issue 5005 (comment 28)
strings.Contains(stack, "runtime.goexit") ||
strings.Contains(stack, "created by runtime.gc") ||
strings.Contains(stack, "dns.interestingGoroutines") ||
strings.Contains(stack, "runtime.MHeap_Scavenger") {
continue
}
gs = append(gs, stack)
}
sort.Strings(gs)
return
}
func goroutineLeaked() error {
if testing.Short() {
// Don't worry about goroutine leaks in -short mode or in
// benchmark mode. Too distracting when there are false positives.
return nil
}
var stackCount map[string]int
for i := 0; i < 5; i++ {
n := 0
stackCount = make(map[string]int)
gs := interestingGoroutines()
for _, g := range gs {
stackCount[g]++
n++
}
if n == 0 {
return nil
}
// Wait for goroutines to schedule and die off:
time.Sleep(100 * time.Millisecond)
}
for stack, count := range stackCount {
fmt.Fprintf(os.Stderr, "%d instances of:\n%s\n", count, stack)
}
return fmt.Errorf("too many goroutines running after dns test(s)")
}

18
vendor/github.com/miekg/dns/msg.go сгенерированный поставляемый
Просмотреть файл

@@ -612,8 +612,8 @@ func UnpackRR(msg []byte, off int) (rr RR, off1 int, err error) {
// If we cannot unpack the whole array, then it will return nil
func unpackRRslice(l int, msg []byte, off int) (dst1 []RR, off1 int, err error) {
var r RR
// Optimistically make dst be the length that was sent
dst := make([]RR, 0, l)
// Don't pre-allocate, l may be under attacker control
var dst []RR
for i := 0; i < l; i++ {
off1 := off
r, off, err = UnpackRR(msg, off)
@@ -811,13 +811,19 @@ func (dns *Msg) Unpack(msg []byte) (err error) {
dns.CheckingDisabled = (dh.Bits & _CD) != 0
dns.Rcode = int(dh.Bits & 0xF)
// If we are at the end of the message we should return *just* the
// header. This can still be useful to the caller. 9.9.9.9 sends these
// when responding with REFUSED for instance.
if off == len(msg) {
return ErrTruncated
// reset sections before returning
dns.Question, dns.Answer, dns.Ns, dns.Extra = nil, nil, nil, nil
return nil
}
// Optimistically use the count given to us in the header
dns.Question = make([]Question, 0, int(dh.Qdcount))
// Qdcount, Ancount, Nscount, Arcount can't be trusted, as they are
// attacker controlled. This means we can't use them to pre-allocate
// slices.
dns.Question = nil
for i := 0; i < int(dh.Qdcount); i++ {
off1 := off
var q Question

3
vendor/github.com/miekg/dns/msg_generate.go сгенерированный поставляемый
Просмотреть файл

@@ -18,8 +18,7 @@ import (
)
var packageHdr = `
// *** DO NOT MODIFY ***
// AUTOGENERATED BY go generate from msg_generate.go
// Code generated by "go run msg_generate.go"; DO NOT EDIT.
package dns

5
vendor/github.com/miekg/dns/msg_helpers.go сгенерированный поставляемый
Просмотреть файл

@@ -406,16 +406,13 @@ Option:
}
edns = append(edns, e)
off += int(optlen)
case EDNS0SUBNET, EDNS0SUBNETDRAFT:
case EDNS0SUBNET:
e := new(EDNS0_SUBNET)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
if code == EDNS0SUBNETDRAFT {
e.DraftOption = true
}
case EDNS0COOKIE:
e := new(EDNS0_COOKIE)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {

53
vendor/github.com/miekg/dns/parse_test.go сгенерированный поставляемый
Просмотреть файл

@@ -145,7 +145,7 @@ func TestTXTEscapeParsing(t *testing.T) {
}
func GenerateDomain(r *rand.Rand, size int) []byte {
dnLen := size % 70 // artificially limit size so there's less to intrepret if a failure occurs
dnLen := size % 70 // artificially limit size so there's less to interpret if a failure occurs
var dn []byte
done := false
for i := 0; i < dnLen && !done; {
@@ -203,7 +203,7 @@ func TestDomainQuick(t *testing.T) {
}
func GenerateTXT(r *rand.Rand, size int) []byte {
rdLen := size % 300 // artificially limit size so there's less to intrepret if a failure occurs
rdLen := size % 300 // artificially limit size so there's less to interpret if a failure occurs
var rd []byte
for i := 0; i < rdLen; {
max := rdLen - 1
@@ -433,6 +433,7 @@ func TestParseClass(t *testing.T) {
// ClassANY can not occur in zone files
// "t.example.com. ANY A 127.0.0.1": "t.example.com. 3600 ANY A 127.0.0.1",
"t.example.com. NONE A 127.0.0.1": "t.example.com. 3600 NONE A 127.0.0.1",
"t.example.com. CLASS255 A 127.0.0.1": "t.example.com. 3600 CLASS255 A 127.0.0.1",
}
for i, o := range tests {
rr, err := NewRR(i)
@@ -1104,6 +1105,7 @@ func TestNewPrivateKey(t *testing.T) {
{RSASHA1, 1024},
{RSASHA256, 2048},
{DSA, 1024},
{ED25519, 256},
}
for _, algo := range algorithms {
@@ -1406,6 +1408,34 @@ func TestParseAVC(t *testing.T) {
}
}
func TestParseCSYNC(t *testing.T) {
syncs := map[string]string{
`example.com. 3600 IN CSYNC 66 3 A NS AAAA`: `example.com. 3600 IN CSYNC 66 3 A NS AAAA`,
}
for s, o := range syncs {
rr, err := NewRR(s)
if err != nil {
t.Error("failed to parse RR: ", err)
continue
}
if rr.String() != o {
t.Errorf("`%s' should be equal to\n`%s', but is `%s'", s, o, rr.String())
}
}
}
func TestParseBadNAPTR(t *testing.T) {
// Should look like: mplus.ims.vodafone.com. 3600 IN NAPTR 10 100 "S" "SIP+D2U" "" _sip._udp.mplus.ims.vodafone.com.
naptr := `mplus.ims.vodafone.com. 3600 IN NAPTR 10 100 S SIP+D2U _sip._udp.mplus.ims.vodafone.com.`
_, err := NewRR(naptr) // parse fails, we should not have leaked a goroutine.
if err == nil {
t.Fatalf("parsing NAPTR should have failed: %s", naptr)
}
if err := goroutineLeaked(); err != nil {
t.Errorf("leaked goroutines: %s", err)
}
}
func TestUnbalancedParens(t *testing.T) {
sig := `example.com. 3600 IN RRSIG MX 15 2 3600 (
1440021600 1438207200 3613 example.com. (
@@ -1413,6 +1443,23 @@ func TestUnbalancedParens(t *testing.T) {
x8A4M3e23mRZ9VrbpMngwcrqNAg== )`
_, err := NewRR(sig)
if err == nil {
t.Fatalf("Failed to detect extra opening brace")
t.Fatalf("failed to detect extra opening brace")
}
}
func TestBad(t *testing.T) {
tests := []string{
`" TYPE257 9 1E12\x00\x105"`,
`" TYPE256 9 5"`,
`" TYPE257 0\"00000000000000400000000000000000000\x00\x10000000000000000000000000000000000 9 l\x16\x01\x005266"`,
}
for i := range tests {
s, err := strconv.Unquote(tests[i])
if err != nil {
t.Fatalf("failed to unquote: %q: %s", tests[i], err)
}
if _, err = NewRR(s); err == nil {
t.Errorf("correctly parsed %q", s)
}
}
}

2
vendor/github.com/miekg/dns/sanitize.go сгенерированный поставляемый
Просмотреть файл

@@ -3,7 +3,7 @@ package dns
// Dedup removes identical RRs from rrs. It preserves the original ordering.
// The lowest TTL of any duplicates is used in the remaining one. Dedup modifies
// rrs.
// m is used to store the RRs temporay. If it is nil a new map will be allocated.
// m is used to store the RRs temporary. If it is nil a new map will be allocated.
func Dedup(rrs []RR, m map[string]RR) []RR {
if m == nil {
m = make(map[string]RR)

66
vendor/github.com/miekg/dns/scan.go сгенерированный поставляемый
Просмотреть файл

@@ -1,23 +1,14 @@
package dns
import (
"fmt"
"io"
"log"
"os"
"path/filepath"
"strconv"
"strings"
)
type debugging bool
const debug debugging = false
func (d debugging) Printf(format string, args ...interface{}) {
if d {
log.Printf(format, args...)
}
}
const maxTok = 2048 // Largest token we can return.
const maxUint16 = 1<<16 - 1
@@ -127,7 +118,7 @@ func NewRR(s string) (RR, error) {
// See NewRR for more documentation.
func ReadRR(q io.Reader, filename string) (RR, error) {
defttl := &ttlState{defaultTtl, false}
r := <-parseZoneHelper(q, ".", defttl, filename, 1)
r := <-parseZoneHelper(q, ".", filename, defttl, 1)
if r == nil {
return nil, nil
}
@@ -164,25 +155,37 @@ func ReadRR(q io.Reader, filename string) (RR, error) {
// The text "; this is comment" is returned in Token.Comment. Comments inside the
// RR are discarded. Comments on a line by themselves are discarded too.
func ParseZone(r io.Reader, origin, file string) chan *Token {
return parseZoneHelper(r, origin, nil, file, 10000)
return parseZoneHelper(r, origin, file, nil, 10000)
}
func parseZoneHelper(r io.Reader, origin string, defttl *ttlState, file string, chansize int) chan *Token {
func parseZoneHelper(r io.Reader, origin, file string, defttl *ttlState, chansize int) chan *Token {
t := make(chan *Token, chansize)
go parseZone(r, origin, defttl, file, t, 0)
go parseZone(r, origin, file, defttl, t, 0)
return t
}
func parseZone(r io.Reader, origin string, defttl *ttlState, f string, t chan *Token, include int) {
func parseZone(r io.Reader, origin, f string, defttl *ttlState, t chan *Token, include int) {
defer func() {
if include == 0 {
close(t)
}
}()
s := scanInit(r)
s, cancel := scanInit(r)
c := make(chan lex)
// Start the lexer
go zlexer(s, c)
defer func() {
cancel()
// zlexer can send up to three tokens, the next one and possibly 2 remainders.
// Do a non-blocking read.
_, ok := <-c
_, ok = <-c
_, ok = <-c
if !ok {
// too bad
}
}()
// 6 possible beginnings of a line, _ is a space
// 0. zRRTYPE -> all omitted until the rrtype
// 1. zOwner _ zRrtype -> class/ttl omitted
@@ -296,16 +299,24 @@ func parseZone(r io.Reader, origin string, defttl *ttlState, f string, t chan *T
return
}
// Start with the new file
r1, e1 := os.Open(l.token)
includePath := l.token
if !filepath.IsAbs(includePath) {
includePath = filepath.Join(filepath.Dir(f), includePath)
}
r1, e1 := os.Open(includePath)
if e1 != nil {
t <- &Token{Error: &ParseError{f, "failed to open `" + l.token + "'", l}}
msg := fmt.Sprintf("failed to open `%s'", l.token)
if !filepath.IsAbs(l.token) {
msg += fmt.Sprintf(" as `%s'", includePath)
}
t <- &Token{Error: &ParseError{f, msg, l}}
return
}
if include+1 > 7 {
t <- &Token{Error: &ParseError{f, "too deeply nested $INCLUDE", l}}
return
}
parseZone(r1, neworigin, defttl, l.token, t, include+1)
parseZone(r1, neworigin, includePath, defttl, t, include+1)
st = zExpectOwnerDir
case zExpectDirTTLBl:
if l.value != zBlank {
@@ -497,14 +508,12 @@ func zlexer(s *scan, c chan lex) {
if stri >= maxTok {
l.token = "token length insufficient for parsing"
l.err = true
debug.Printf("[%+v]", l.token)
c <- l
return
}
if comi >= maxTok {
l.token = "comment length insufficient for parsing"
l.err = true
debug.Printf("[%+v]", l.token)
c <- l
return
}
@@ -547,7 +556,6 @@ func zlexer(s *scan, c chan lex) {
case "$GENERATE":
l.value = zDirGenerate
}
debug.Printf("[7 %+v]", l.token)
c <- l
} else {
l.value = zString
@@ -569,6 +577,7 @@ func zlexer(s *scan, c chan lex) {
return
}
l.value = zRrtpe
rrtype = true
l.torc = t
}
}
@@ -589,16 +598,14 @@ func zlexer(s *scan, c chan lex) {
}
}
}
debug.Printf("[6 %+v]", l.token)
c <- l
}
stri = 0
// I reverse space stuff here
if !space && !commt {
l.value = zBlank
l.token = " "
l.length = 1
debug.Printf("[5 %+v]", l.token)
c <- l
}
owner = false
@@ -621,7 +628,6 @@ func zlexer(s *scan, c chan lex) {
l.token = string(str[:stri])
l.tokenUpper = strings.ToUpper(l.token)
l.length = stri
debug.Printf("[4 %+v]", l.token)
c <- l
stri = 0
}
@@ -659,7 +665,6 @@ func zlexer(s *scan, c chan lex) {
l.tokenUpper = l.token
l.length = 1
l.comment = string(com[:comi])
debug.Printf("[3 %+v %+v]", l.token, l.comment)
c <- l
l.comment = ""
comi = 0
@@ -685,14 +690,12 @@ func zlexer(s *scan, c chan lex) {
rrtype = true
}
}
debug.Printf("[2 %+v]", l.token)
c <- l
}
l.value = zNewline
l.token = "\n"
l.tokenUpper = l.token
l.length = 1
debug.Printf("[1 %+v]", l.token)
c <- l
stri = 0
commt = false
@@ -738,7 +741,6 @@ func zlexer(s *scan, c chan lex) {
l.tokenUpper = strings.ToUpper(l.token)
l.length = stri
debug.Printf("[%+v]", l.token)
c <- l
stri = 0
}
@@ -774,7 +776,6 @@ func zlexer(s *scan, c chan lex) {
l.token = "extra closing brace"
l.tokenUpper = l.token
l.err = true
debug.Printf("[%+v]", l.token)
c <- l
return
}
@@ -800,7 +801,6 @@ func zlexer(s *scan, c chan lex) {
l.tokenUpper = strings.ToUpper(l.token)
l.length = stri
l.value = zString
debug.Printf("[%+v]", l.token)
c <- l
}
if brace != 0 {

101
vendor/github.com/miekg/dns/scan_rr.go сгенерированный поставляемый
Просмотреть файл

@@ -1024,6 +1024,56 @@ func setOPENPGPKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, strin
return rr, nil, c1
}
func setCSYNC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(CSYNC)
rr.Hdr = h
l := <-c
if l.length == 0 { // dynamic update rr.
return rr, nil, l.comment
}
j, e := strconv.ParseUint(l.token, 10, 32)
if e != nil {
// Serial must be a number
return nil, &ParseError{f, "bad CSYNC serial", l}, ""
}
rr.Serial = uint32(j)
<-c // zBlank
l = <-c
j, e = strconv.ParseUint(l.token, 10, 16)
if e != nil {
// Serial must be a number
return nil, &ParseError{f, "bad CSYNC flags", l}, ""
}
rr.Flags = uint16(j)
rr.TypeBitMap = make([]uint16, 0)
var (
k uint16
ok bool
)
l = <-c
for l.value != zNewline && l.value != zEOF {
switch l.value {
case zBlank:
// Ok
case zString:
if k, ok = StringToType[l.tokenUpper]; !ok {
if k, ok = typeToInt(l.tokenUpper); !ok {
return nil, &ParseError{f, "bad CSYNC TypeBitMap", l}, ""
}
}
rr.TypeBitMap = append(rr.TypeBitMap, k)
default:
return nil, &ParseError{f, "bad CSYNC TypeBitMap", l}, ""
}
l = <-c
}
return rr, nil, l.comment
}
func setSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
r, e, s := setRRSIG(h, c, o, f)
if r != nil {
@@ -1797,7 +1847,7 @@ func setURI(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if err != nil {
return nil, err, ""
}
if len(s) > 1 {
if len(s) != 1 {
return nil, &ParseError{f, "bad URI Target", l}, ""
}
rr.Target = s[0]
@@ -2027,13 +2077,58 @@ func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if e != nil {
return nil, e, ""
}
if len(s) > 1 {
if len(s) != 1 {
return nil, &ParseError{f, "bad CAA Value", l}, ""
}
rr.Value = s[0]
return rr, nil, c1
}
func setTKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(TKEY)
rr.Hdr = h
l := <-c
// Algorithm
if l.value != zString {
return nil, &ParseError{f, "bad TKEY algorithm", l}, ""
}
rr.Algorithm = l.token
<-c // zBlank
// Get the key length and key values
l = <-c
i, err := strconv.ParseUint(l.token, 10, 8)
if err != nil || l.err {
return nil, &ParseError{f, "bad TKEY key length", l}, ""
}
rr.KeySize = uint16(i)
<-c // zBlank
l = <-c
if l.value != zString {
return nil, &ParseError{f, "bad TKEY key", l}, ""
}
rr.Key = l.token
<-c // zBlank
// Get the otherdata length and string data
l = <-c
i, err = strconv.ParseUint(l.token, 10, 8)
if err != nil || l.err {
return nil, &ParseError{f, "bad TKEY otherdata length", l}, ""
}
rr.OtherLen = uint16(i)
<-c // zBlank
l = <-c
if l.value != zString {
return nil, &ParseError{f, "bad TKEY otherday", l}, ""
}
rr.OtherData = l.token
return rr, nil, ""
}
var typeToparserFunc = map[uint16]parserFunc{
TypeAAAA: {setAAAA, false},
TypeAFSDB: {setAFSDB, false},
@@ -2043,6 +2138,7 @@ var typeToparserFunc = map[uint16]parserFunc{
TypeCDNSKEY: {setCDNSKEY, true},
TypeCERT: {setCERT, true},
TypeCNAME: {setCNAME, false},
TypeCSYNC: {setCSYNC, true},
TypeDHCID: {setDHCID, true},
TypeDLV: {setDLV, true},
TypeDNAME: {setDNAME, false},
@@ -2099,4 +2195,5 @@ var typeToparserFunc = map[uint16]parserFunc{
TypeUINFO: {setUINFO, true},
TypeURI: {setURI, true},
TypeX25: {setX25, false},
TypeTKEY: {setTKEY, true},
}

17
vendor/github.com/miekg/dns/scanner.go сгенерированный поставляемый
Просмотреть файл

@@ -4,6 +4,7 @@ package dns
import (
"bufio"
"context"
"io"
"text/scanner"
)
@@ -12,13 +13,18 @@ type scan struct {
src *bufio.Reader
position scanner.Position
eof bool // Have we just seen a eof
ctx context.Context
}
func scanInit(r io.Reader) *scan {
func scanInit(r io.Reader) (*scan, context.CancelFunc) {
s := new(scan)
s.src = bufio.NewReader(r)
s.position.Line = 1
return s
ctx, cancel := context.WithCancel(context.Background())
s.ctx = ctx
return s, cancel
}
// tokenText returns the next byte from the input
@@ -27,6 +33,13 @@ func (s *scan) tokenText() (byte, error) {
if err != nil {
return c, err
}
select {
case <-s.ctx.Done():
return c, context.Canceled
default:
break
}
// delay the newline handling until the next token is delivered,
// fixes off-by-one errors when reporting a parse error.
if s.eof == true {

27
vendor/github.com/miekg/dns/server.go сгенерированный поставляемый
Просмотреть файл

@@ -285,7 +285,7 @@ type Server struct {
WriteTimeout time.Duration
// TCP idle timeout for multiple queries, if nil, defaults to 8 * time.Second (RFC 5966).
IdleTimeout func() time.Duration
// Secret(s) for Tsig map[<zonename>]<base64 secret>.
// Secret(s) for Tsig map[<zonename>]<base64 secret>. The zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2).
TsigSecret map[string]string
// Unsafe instructs the server to disregard any sanity checks and directly hand the message to
// the handler. It will specifically not check if the query has the QR bit not set.
@@ -460,6 +460,12 @@ func (srv *Server) serveTCP(l net.Listener) error {
// deadline is not used here
for {
rw, err := l.Accept()
srv.lock.RLock()
if !srv.started {
srv.lock.RUnlock()
return nil
}
srv.lock.RUnlock()
if err != nil {
if neterr, ok := err.(net.Error); ok && neterr.Temporary() {
continue
@@ -467,12 +473,6 @@ func (srv *Server) serveTCP(l net.Listener) error {
return err
}
m, err := reader.ReadTCP(rw, rtimeout)
srv.lock.RLock()
if !srv.started {
srv.lock.RUnlock()
return nil
}
srv.lock.RUnlock()
if err != nil {
continue
}
@@ -509,6 +509,12 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
}
srv.lock.RUnlock()
if err != nil {
if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
continue
}
return err
}
if len(m) < headerSize {
continue
}
go srv.serve(s.RemoteAddr(), handler, m, l, s, nil)
@@ -626,11 +632,8 @@ func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *S
conn.SetReadDeadline(time.Now().Add(timeout))
m := make([]byte, srv.UDPSize)
n, s, err := ReadFromSessionUDP(conn, m)
if err != nil || n == 0 {
if err != nil {
return nil, nil, err
}
return nil, nil, ErrShortRead
if err != nil {
return nil, nil, err
}
m = m[:n]
return m, s, nil

4
vendor/github.com/miekg/dns/server_test.go сгенерированный поставляемый
Просмотреть файл

@@ -654,11 +654,11 @@ func TestServerStartStopRace(t *testing.T) {
s := &Server{}
s, _, _, err = RunLocalUDPServerWithFinChan(":0")
if err != nil {
t.Fatalf("Could not start server: %s", err)
t.Fatalf("could not start server: %s", err)
}
go func() {
if err := s.Shutdown(); err != nil {
t.Fatalf("Could not stop server: %s", err)
t.Fatalf("could not stop server: %s", err)
}
}()
}

43
vendor/github.com/miekg/dns/types.go сгенерированный поставляемый
Просмотреть файл

@@ -78,6 +78,7 @@ const (
TypeCDS uint16 = 59
TypeCDNSKEY uint16 = 60
TypeOPENPGPKEY uint16 = 61
TypeCSYNC uint16 = 62
TypeSPF uint16 = 99
TypeUINFO uint16 = 100
TypeUID uint16 = 101
@@ -1012,14 +1013,18 @@ type TKEY struct {
Mode uint16
Error uint16
KeySize uint16
Key string
Key string `dns:"size-hex:KeySize"`
OtherLen uint16
OtherData string
OtherData string `dns:"size-hex:OtherLen"`
}
// TKEY has no official presentation format, but this will suffice.
func (rr *TKEY) String() string {
// It has no presentation format
return ""
s := "\n;; TKEY PSEUDOSECTION:\n"
s += rr.Hdr.String() + " " + rr.Algorithm + " " +
strconv.Itoa(int(rr.KeySize)) + " " + rr.Key + " " +
strconv.Itoa(int(rr.OtherLen)) + " " + rr.OtherData
return s
}
// RFC3597 represents an unknown/generic RR. See RFC 3597.
@@ -1267,6 +1272,36 @@ type OPENPGPKEY struct {
func (rr *OPENPGPKEY) String() string { return rr.Hdr.String() + rr.PublicKey }
// CSYNC RR. See RFC 7477.
type CSYNC struct {
Hdr RR_Header
Serial uint32
Flags uint16
TypeBitMap []uint16 `dns:"nsec"`
}
func (rr *CSYNC) String() string {
s := rr.Hdr.String() + strconv.FormatInt(int64(rr.Serial), 10) + " " + strconv.Itoa(int(rr.Flags))
for i := 0; i < len(rr.TypeBitMap); i++ {
s += " " + Type(rr.TypeBitMap[i]).String()
}
return s
}
func (rr *CSYNC) len() int {
l := rr.Hdr.len() + 4 + 2
lastwindow := uint32(2 ^ 32 + 1)
for _, t := range rr.TypeBitMap {
window := t / 256
if uint32(window) != lastwindow {
l += 1 + 32
}
lastwindow = uint32(window)
}
return l
}
// TimeToString translates the RRSIG's incep. and expir. times to the
// string representation used when printing the record.
// It takes serial arithmetic (RFC 1982) into account.

6
vendor/github.com/miekg/dns/types_generate.go сгенерированный поставляемый
Просмотреть файл

@@ -23,11 +23,11 @@ var skipLen = map[string]struct{}{
"NSEC": {},
"NSEC3": {},
"OPT": {},
"CSYNC": {},
}
var packageHdr = `
// *** DO NOT MODIFY ***
// AUTOGENERATED BY go generate from types_generate.go
// Code generated by "go run types_generate.go"; DO NOT EDIT.
package dns
@@ -181,6 +181,8 @@ func main() {
fallthrough
case st.Tag(i) == `dns:"base64"`:
o("l += base64.StdEncoding.DecodedLen(len(rr.%s))\n")
case strings.HasPrefix(st.Tag(i), `dns:"size-hex:`): // this has an extra field where the length is stored
o("l += len(rr.%s)/2\n")
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`):
fallthrough
case st.Tag(i) == `dns:"hex"`:

52
vendor/github.com/miekg/dns/udp.go сгенерированный поставляемый
Просмотреть файл

@@ -4,6 +4,9 @@ package dns
import (
"net"
"golang.org/x/net/ipv4"
"golang.org/x/net/ipv6"
)
// SessionUDP holds the remote address and the associated
@@ -34,12 +37,53 @@ func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, e
return n, err
}
func setUDPSocketOptions(conn *net.UDPConn) error {
// Try setting the flags for both families and ignore the errors unless they
// both error.
err6 := ipv6.NewPacketConn(conn).SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true)
err4 := ipv4.NewPacketConn(conn).SetControlMessage(ipv4.FlagDst|ipv4.FlagInterface, true)
if err6 != nil && err4 != nil {
return err4
}
return nil
}
// parseDstFromOOB takes oob data and returns the destination IP.
func parseDstFromOOB(oob []byte) net.IP {
// Start with IPv6 and then fallback to IPv4
// TODO(fastest963): Figure out a way to prefer one or the other. Looking at
// the lvl of the header for a 0 or 41 isn't cross-platform.
var dst net.IP
cm6 := new(ipv6.ControlMessage)
if cm6.Parse(oob) == nil {
dst = cm6.Dst
}
if dst == nil {
cm4 := new(ipv4.ControlMessage)
if cm4.Parse(oob) == nil {
dst = cm4.Dst
}
}
return dst
}
// correctSource takes oob data and returns new oob data with the Src equal to the Dst
func correctSource(oob []byte) []byte {
dst, err := parseUDPSocketDst(oob)
// If the destination could not be determined, ignore.
if err != nil || dst == nil {
dst := parseDstFromOOB(oob)
if dst == nil {
return nil
}
return marshalUDPSocketSrc(dst)
// If the dst is definitely an IPv6, then use ipv6's ControlMessage to
// respond otherwise use ipv4's because ipv6's marshal ignores ipv4
// addresses.
if dst.To4() == nil {
cm := new(ipv6.ControlMessage)
cm.Src = dst
oob = cm.Marshal()
} else {
cm := new(ipv4.ControlMessage)
cm.Src = dst
oob = cm.Marshal()
}
return oob
}

220
vendor/github.com/miekg/dns/udp_linux.go сгенерированный поставляемый
Просмотреть файл

@@ -1,220 +0,0 @@
// +build linux,!appengine
package dns
// See:
// * http://stackoverflow.com/questions/3062205/setting-the-source-ip-for-a-udp-socket and
// * http://blog.powerdns.com/2012/10/08/on-binding-datagram-udp-sockets-to-the-any-addresses/
//
// Why do we need this: When listening on 0.0.0.0 with UDP so kernel decides what is the outgoing
// interface, this might not always be the correct one. This code will make sure the egress
// packet's interface matched the ingress' one.
import (
"net"
"syscall"
"unsafe"
"github.com/miekg/dns/internal/socket"
)
const (
sizeofInet6Pktinfo = 0x14
sizeofInetPktinfo = 0xc
protocolIP = 0
protocolIPv6 = 41
)
type inetPktinfo struct {
Ifindex int32
Spec_dst [4]byte /* in_addr */
Addr [4]byte /* in_addr */
}
type inet6Pktinfo struct {
Addr [16]byte /* in6_addr */
Ifindex int32
}
type inetControlMessage struct {
Src net.IP // source address, specifying only
Dst net.IP // destination address, receiving only
}
// setUDPSocketOptions sets the UDP socket options.
// This function is implemented on a per platform basis. See udp_*.go for more details
func setUDPSocketOptions(conn *net.UDPConn) error {
sa, err := getUDPSocketName(conn)
if err != nil {
return err
}
switch sa.(type) {
case *syscall.SockaddrInet6:
v6only, err := getUDPSocketOptions6Only(conn)
if err != nil {
return err
}
setUDPSocketOptions6(conn)
if !v6only {
setUDPSocketOptions4(conn)
}
case *syscall.SockaddrInet4:
setUDPSocketOptions4(conn)
}
return nil
}
// setUDPSocketOptions4 prepares the v4 socket for sessions.
func setUDPSocketOptions4(conn *net.UDPConn) error {
file, err := conn.File()
if err != nil {
return err
}
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil {
file.Close()
return err
}
// Calling File() above results in the connection becoming blocking, we must fix that.
// See https://github.com/miekg/dns/issues/279
err = syscall.SetNonblock(int(file.Fd()), true)
if err != nil {
file.Close()
return err
}
file.Close()
return nil
}
// setUDPSocketOptions6 prepares the v6 socket for sessions.
func setUDPSocketOptions6(conn *net.UDPConn) error {
file, err := conn.File()
if err != nil {
return err
}
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1); err != nil {
file.Close()
return err
}
err = syscall.SetNonblock(int(file.Fd()), true)
if err != nil {
file.Close()
return err
}
file.Close()
return nil
}
// getUDPSocketOption6Only return true if the socket is v6 only and false when it is v4/v6 combined
// (dualstack).
func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) {
file, err := conn.File()
if err != nil {
return false, err
}
// dual stack. See http://stackoverflow.com/questions/1618240/how-to-support-both-ipv4-and-ipv6-connections
v6only, err := syscall.GetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY)
if err != nil {
file.Close()
return false, err
}
file.Close()
return v6only == 1, nil
}
func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) {
file, err := conn.File()
if err != nil {
return nil, err
}
defer file.Close()
return syscall.Getsockname(int(file.Fd()))
}
// marshalInetPacketInfo marshals a ipv4 control message, returning
// the byte slice for the next marshal, if any
func marshalInetPacketInfo(b []byte, cm *inetControlMessage) []byte {
m := socket.ControlMessage(b)
m.MarshalHeader(protocolIP, syscall.IP_PKTINFO, sizeofInetPktinfo)
if cm != nil {
pi := (*inetPktinfo)(unsafe.Pointer(&m.Data(sizeofInetPktinfo)[0]))
if ip := cm.Src.To4(); ip != nil {
copy(pi.Spec_dst[:], ip)
}
}
return m.Next(sizeofInetPktinfo)
}
// marshalInet6PacketInfo marshals a ipv6 control message, returning
// the byte slice for the next marshal, if any
func marshalInet6PacketInfo(b []byte, cm *inetControlMessage) []byte {
m := socket.ControlMessage(b)
m.MarshalHeader(protocolIPv6, syscall.IPV6_PKTINFO, sizeofInet6Pktinfo)
if cm != nil {
pi := (*inet6Pktinfo)(unsafe.Pointer(&m.Data(sizeofInet6Pktinfo)[0]))
if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
copy(pi.Addr[:], ip)
}
}
return m.Next(sizeofInet6Pktinfo)
}
func parseInetPacketInfo(cm *inetControlMessage, b []byte) {
pi := (*inetPktinfo)(unsafe.Pointer(&b[0]))
if len(cm.Dst) < net.IPv4len {
cm.Dst = make(net.IP, net.IPv4len)
}
copy(cm.Dst, pi.Addr[:])
}
func parseInet6PacketInfo(cm *inetControlMessage, b []byte) {
pi := (*inet6Pktinfo)(unsafe.Pointer(&b[0]))
if len(cm.Dst) < net.IPv6len {
cm.Dst = make(net.IP, net.IPv6len)
}
copy(cm.Dst, pi.Addr[:])
}
// parseUDPSocketDst takes out-of-band data from ReadMsgUDP and parses it for
// the Dst address
func parseUDPSocketDst(oob []byte) (net.IP, error) {
cm := new(inetControlMessage)
ms, err := socket.ControlMessage(oob).Parse()
if err != nil {
return nil, err
}
for _, m := range ms {
lvl, typ, l, err := m.ParseHeader()
if err != nil {
return nil, err
}
if lvl == protocolIPv6 { // IPv6
if typ == syscall.IPV6_PKTINFO && l >= sizeofInet6Pktinfo {
parseInet6PacketInfo(cm, m.Data(l))
}
} else if lvl == protocolIP { // IPv4
if typ == syscall.IP_PKTINFO && l >= sizeofInetPktinfo {
parseInetPacketInfo(cm, m.Data(l))
}
}
}
return cm.Dst, nil
}
// marshalUDPSocketSrc takes the given src address and returns out-of-band data
// to give to WriteMsgUDP
func marshalUDPSocketSrc(src net.IP) []byte {
var oob []byte
// If the dst is definitely an ipv6, then use ipv6 control to respond
// otherwise use ipv4 because the ipv6 marshal ignores ipv4 messages.
// See marshalInet6PacketInfo
cm := new(inetControlMessage)
cm.Src = src
if src.To4() == nil {
oob = make([]byte, socket.ControlMessageSpace(sizeofInet6Pktinfo))
marshalInet6PacketInfo(oob, cm)
} else {
oob = make([]byte, socket.ControlMessageSpace(sizeofInetPktinfo))
marshalInetPacketInfo(oob, cm)
}
return oob
}

68
vendor/github.com/miekg/dns/udp_linux_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,68 +0,0 @@
// +build linux,!appengine
package dns
import (
"bytes"
"net"
"testing"
)
func TestParseUDPSocketDst(t *testing.T) {
// dst is :ffff:100.100.100.100
oob := []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 100, 100, 100, 100, 2, 0, 0, 0}
dst, err := parseUDPSocketDst(oob)
if err != nil {
t.Fatalf("error parsing ipv6 oob: %v", err)
}
dst4 := dst.To4()
if dst4 == nil {
t.Errorf("failed to parse ipv4: %v", dst)
} else if dst4.String() != "100.100.100.100" {
t.Errorf("unexpected ipv4: %v", dst4)
}
// dst is 2001:db8::1
oob = []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 32, 1, 13, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}
dst, err = parseUDPSocketDst(oob)
if err != nil {
t.Fatalf("error parsing ipv6 oob: %v", err)
}
dst6 := dst.To16()
if dst6 == nil {
t.Errorf("failed to parse ipv6: %v", dst)
} else if dst6.String() != "2001:db8::1" {
t.Errorf("unexpected ipv6: %v", dst4)
}
// dst is 100.100.100.100 but was received on 10.10.10.10
oob = []byte{28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 10, 10, 10, 10, 100, 100, 100, 100, 0, 0, 0, 0}
dst, err = parseUDPSocketDst(oob)
if err != nil {
t.Fatalf("error parsing ipv4 oob: %v", err)
}
dst4 = dst.To4()
if dst4 == nil {
t.Errorf("failed to parse ipv4: %v", dst)
} else if dst4.String() != "100.100.100.100" {
t.Errorf("unexpected ipv4: %v", dst4)
}
}
func TestMarshalUDPSocketSrc(t *testing.T) {
// src is 100.100.100.100
exoob := []byte{28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 100, 100, 100, 100, 0, 0, 0, 0, 0, 0, 0, 0}
oob := marshalUDPSocketSrc(net.ParseIP("100.100.100.100"))
if !bytes.Equal(exoob, oob) {
t.Errorf("expected ipv4 oob:\n%v", exoob)
t.Errorf("actual ipv4 oob:\n%v", oob)
}
// src is 2001:db8::1
exoob = []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 32, 1, 13, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}
oob = marshalUDPSocketSrc(net.ParseIP("2001:db8::1"))
if !bytes.Equal(exoob, oob) {
t.Errorf("expected ipv6 oob:\n%v", exoob)
t.Errorf("actual ipv6 oob:\n%v", oob)
}
}

17
vendor/github.com/miekg/dns/udp_other.go сгенерированный поставляемый
Просмотреть файл

@@ -1,17 +0,0 @@
// +build !linux appengine
package dns
import (
"net"
)
// These do nothing. See udp_linux.go for an example of how to implement this.
// We tried to adhire to some kind of naming scheme.
func setUDPSocketOptions(conn *net.UDPConn) error { return nil }
func setUDPSocketOptions4(conn *net.UDPConn) error { return nil }
func setUDPSocketOptions6(conn *net.UDPConn) error { return nil }
func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) { return false, nil }
func parseUDPSocketDst(oob []byte) (net.IP, error) { return nil, nil }
func marshalUDPSocketSrc(src net.IP) []byte { return nil }

126
vendor/github.com/miekg/dns/udp_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,126 @@
// +build linux,!appengine
package dns
import (
"bytes"
"net"
"strings"
"testing"
"time"
"golang.org/x/net/ipv4"
"golang.org/x/net/ipv6"
)
func TestSetUDPSocketOptions(t *testing.T) {
// returns an error if we cannot resolve that address
testFamily := func(n, addr string) error {
a, err := net.ResolveUDPAddr(n, addr)
if err != nil {
return err
}
c, err := net.ListenUDP(n, a)
if err != nil {
return err
}
if err := setUDPSocketOptions(c); err != nil {
t.Fatalf("failed to set socket options: %v", err)
}
ch := make(chan *SessionUDP)
go func() {
// Set some deadline so this goroutine doesn't hang forever
c.SetReadDeadline(time.Now().Add(time.Minute))
b := make([]byte, 1)
_, sess, err := ReadFromSessionUDP(c, b)
if err != nil {
t.Fatalf("failed to read from conn: %v", err)
}
ch <- sess
}()
c2, err := net.Dial("udp", c.LocalAddr().String())
if err != nil {
t.Fatalf("failed to dial udp: %v", err)
}
if _, err := c2.Write([]byte{1}); err != nil {
t.Fatalf("failed to write to conn: %v", err)
}
sess := <-ch
if len(sess.context) == 0 {
t.Fatalf("empty session context: %v", sess)
}
ip := parseDstFromOOB(sess.context)
if ip == nil {
t.Fatalf("failed to parse dst: %v", sess)
}
if !strings.Contains(c.LocalAddr().String(), ip.String()) {
t.Fatalf("dst was different than listen addr: %v != %v", ip.String(), c.LocalAddr().String())
}
return nil
}
// we require that ipv4 be supported
if err := testFamily("udp4", "127.0.0.1:0"); err != nil {
t.Fatalf("failed to test socket options on IPv4: %v", err)
}
// IPv6 might not be supported so these will just log
if err := testFamily("udp6", "[::1]:0"); err != nil {
t.Logf("failed to test socket options on IPv6-only: %v", err)
}
if err := testFamily("udp", "[::1]:0"); err != nil {
t.Logf("failed to test socket options on IPv6/IPv4: %v", err)
}
}
func TestParseDstFromOOB(t *testing.T) {
// dst is :ffff:100.100.100.100
oob := []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 100, 100, 100, 100, 2, 0, 0, 0}
dst := parseDstFromOOB(oob)
dst4 := dst.To4()
if dst4 == nil {
t.Errorf("failed to parse IPv4 in IPv6: %v", dst)
} else if dst4.String() != "100.100.100.100" {
t.Errorf("unexpected IPv4: %v", dst4)
}
// dst is 2001:db8::1
oob = []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 32, 1, 13, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}
dst = parseDstFromOOB(oob)
dst6 := dst.To16()
if dst6 == nil {
t.Errorf("failed to parse IPv6: %v", dst)
} else if dst6.String() != "2001:db8::1" {
t.Errorf("unexpected IPv6: %v", dst4)
}
// dst is 100.100.100.100 but was received on 10.10.10.10
oob = []byte{28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 10, 10, 10, 10, 100, 100, 100, 100, 0, 0, 0, 0}
dst = parseDstFromOOB(oob)
dst4 = dst.To4()
if dst4 == nil {
t.Errorf("failed to parse IPv4: %v", dst)
} else if dst4.String() != "100.100.100.100" {
t.Errorf("unexpected IPv4: %v", dst4)
}
}
func TestCorrectSource(t *testing.T) {
// dst is :ffff:100.100.100.100 which should be counted as IPv4
oob := []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 100, 100, 100, 100, 2, 0, 0, 0}
soob := correctSource(oob)
cm4 := new(ipv4.ControlMessage)
cm4.Src = net.ParseIP("100.100.100.100")
if !bytes.Equal(soob, cm4.Marshal()) {
t.Errorf("unexpected oob for ipv4 address: %v", soob)
}
// dst is 2001:db8::1
oob = []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 32, 1, 13, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}
soob = correctSource(oob)
cm6 := new(ipv6.ControlMessage)
cm6.Src = net.ParseIP("2001:db8::1")
if !bytes.Equal(soob, cm6.Marshal()) {
t.Errorf("unexpected oob for IPv6 address: %v", soob)
}
}

7
vendor/github.com/miekg/dns/udp_windows.go сгенерированный поставляемый
Просмотреть файл

@@ -14,6 +14,7 @@ func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
// net.UDPAddr.
// TODO(fastest963): Once go1.10 is released, use ReadMsgUDP.
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
n, raddr, err := conn.ReadFrom(b)
if err != nil {
@@ -24,7 +25,13 @@ func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
}
// WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
// TODO(fastest963): Once go1.10 is released, use WriteMsgUDP.
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
n, err := conn.WriteTo(b, session.raddr)
return n, err
}
// TODO(fastest963): Once go1.10 is released and we can use *MsgUDP methods
// use the standard method in udp.go for these.
func setUDPSocketOptions(*net.UDPConn) error { return nil }
func parseDstFromOOB([]byte, net.IP) net.IP { return nil }

8
vendor/github.com/miekg/dns/update_test.go сгенерированный поставляемый
Просмотреть файл

@@ -119,15 +119,15 @@ func TestPreReqAndRemovals(t *testing.T) {
;example.org. IN SOA
;; ANSWER SECTION:
name_used. 0 ANY ANY
name_used. 0 CLASS255 ANY
name_not_used. 0 NONE ANY
rrset_used1. 0 ANY A
rrset_used1. 0 CLASS255 A
rrset_used2. 3600 IN A 127.0.0.1
rrset_not_used. 0 NONE A
;; AUTHORITY SECTION:
remove1. 0 ANY ANY
remove2. 0 ANY A
remove1. 0 CLASS255 ANY
remove2. 0 CLASS255 A
remove3. 0 NONE A 127.0.0.1
insert. 3600 IN A 127.0.0.1
`

10
vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/.gitattributes сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,10 @@
# Treat all files in this repo as binary, with no git magic updating
# line endings. Windows users contributing to Go will need to use a
# modern version of git and editors capable of LF line endings.
#
# We'll prevent accidental CRLF line endings from entering the repo
# via the git-review gofmt checks.
#
# See golang.org/issue/9281
* -text

2
vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/.gitignore сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,2 @@
# Add no patterns to .hgignore except for files generated by the build.
last-change

3
vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/AUTHORS сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -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.

31
vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/CONTRIBUTING.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,31 @@
# Contributing to Go
Go is an open source project.
It is the work of hundreds of contributors. We appreciate your help!
## Filing issues
When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:
1. What version of Go are you using (`go version`)?
2. What operating system and processor architecture are you using?
3. What did you do?
4. What did you expect to see?
5. What did you see instead?
General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
The gophers there will answer or ask you to file an issue if you've tripped over a bug.
## Contributing code
Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
before sending patches.
**We do not accept GitHub pull requests**
(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review).
Unless otherwise noted, the Go source files are distributed under
the BSD-style license found in the LICENSE file.

3
vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/CONTRIBUTORS сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -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.

27
vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/LICENSE сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,27 @@
Copyright (c) 2009 The Go Authors. 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.

22
vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/PATENTS сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,22 @@
Additional IP Rights Grant (Patents)
"This implementation" means the copyrightable works distributed by
Google as part of the Go project.
Google hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer and otherwise run, modify and propagate the contents of this
implementation of Go, where such license applies only to those patent
claims, both currently owned or controlled by Google and acquired in
the future, licensable by Google that are necessarily infringed by this
implementation of Go. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of Go or any code incorporated within this
implementation of Go constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of Go
shall terminate as of the date such litigation is filed.

21
vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/README.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,21 @@
# Go Cryptography
This repository holds supplementary Go cryptography libraries.
## Download/Install
The easiest way to install is to run `go get -u golang.org/x/crypto/...`. You
can also manually git clone the repository to `$GOPATH/src/golang.org/x/crypto`.
## Report Issues / Send Patches
This repository uses Gerrit for code changes. To learn how to submit changes to
this repository, see https://golang.org/doc/contribute.html.
The main issue tracker for the crypto repository is located at
https://github.com/golang/go/issues. Prefix your issue with "x/crypto:" in the
subject line, so it is easy to find.
Note that contributions to the cryptography package receive additional scrutiny
due to their sensitive nature. Patches may take longer than normal to receive
feedback.

1058
vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/acme.go сгенерированный поставляемый Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

1352
vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/acme_test.go сгенерированный поставляемый Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

821
vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/autocert.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,821 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package autocert provides automatic access to certificates from Let's Encrypt
// and any other ACME-based CA.
//
// This package is a work in progress and makes no API stability promises.
package autocert
import (
"bytes"
"context"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"errors"
"fmt"
"io"
mathrand "math/rand"
"net/http"
"strconv"
"strings"
"sync"
"time"
"golang.org/x/crypto/acme"
)
// createCertRetryAfter is how much time to wait before removing a failed state
// entry due to an unsuccessful createCert call.
// This is a variable instead of a const for testing.
// TODO: Consider making it configurable or an exp backoff?
var createCertRetryAfter = time.Minute
// pseudoRand is safe for concurrent use.
var pseudoRand *lockedMathRand
func init() {
src := mathrand.NewSource(timeNow().UnixNano())
pseudoRand = &lockedMathRand{rnd: mathrand.New(src)}
}
// AcceptTOS is a Manager.Prompt function that always returns true to
// indicate acceptance of the CA's Terms of Service during account
// registration.
func AcceptTOS(tosURL string) bool { return true }
// HostPolicy specifies which host names the Manager is allowed to respond to.
// It returns a non-nil error if the host should be rejected.
// The returned error is accessible via tls.Conn.Handshake and its callers.
// See Manager's HostPolicy field and GetCertificate method docs for more details.
type HostPolicy func(ctx context.Context, host string) error
// HostWhitelist returns a policy where only the specified host names are allowed.
// Only exact matches are currently supported. Subdomains, regexp or wildcard
// will not match.
func HostWhitelist(hosts ...string) HostPolicy {
whitelist := make(map[string]bool, len(hosts))
for _, h := range hosts {
whitelist[h] = true
}
return func(_ context.Context, host string) error {
if !whitelist[host] {
return errors.New("acme/autocert: host not configured")
}
return nil
}
}
// defaultHostPolicy is used when Manager.HostPolicy is not set.
func defaultHostPolicy(context.Context, string) error {
return nil
}
// Manager is a stateful certificate manager built on top of acme.Client.
// It obtains and refreshes certificates automatically,
// as well as providing them to a TLS server via tls.Config.
//
// You must specify a cache implementation, such as DirCache,
// to reuse obtained certificates across program restarts.
// Otherwise your server is very likely to exceed the certificate
// issuer's request rate limits.
type Manager struct {
// Prompt specifies a callback function to conditionally accept a CA's Terms of Service (TOS).
// The registration may require the caller to agree to the CA's TOS.
// If so, Manager calls Prompt with a TOS URL provided by the CA. Prompt should report
// whether the caller agrees to the terms.
//
// To always accept the terms, the callers can use AcceptTOS.
Prompt func(tosURL string) bool
// Cache optionally stores and retrieves previously-obtained certificates.
// If nil, certs will only be cached for the lifetime of the Manager.
//
// Manager passes the Cache certificates data encoded in PEM, with private/public
// parts combined in a single Cache.Put call, private key first.
Cache Cache
// HostPolicy controls which domains the Manager will attempt
// to retrieve new certificates for. It does not affect cached certs.
//
// If non-nil, HostPolicy is called before requesting a new cert.
// If nil, all hosts are currently allowed. This is not recommended,
// as it opens a potential attack where clients connect to a server
// by IP address and pretend to be asking for an incorrect host name.
// Manager will attempt to obtain a certificate for that host, incorrectly,
// eventually reaching the CA's rate limit for certificate requests
// and making it impossible to obtain actual certificates.
//
// See GetCertificate for more details.
HostPolicy HostPolicy
// RenewBefore optionally specifies how early certificates should
// be renewed before they expire.
//
// If zero, they're renewed 30 days before expiration.
RenewBefore time.Duration
// Client is used to perform low-level operations, such as account registration
// and requesting new certificates.
// If Client is nil, a zero-value acme.Client is used with acme.LetsEncryptURL
// directory endpoint and a newly-generated ECDSA P-256 key.
//
// Mutating the field after the first call of GetCertificate method will have no effect.
Client *acme.Client
// Email optionally specifies a contact email address.
// This is used by CAs, such as Let's Encrypt, to notify about problems
// with issued certificates.
//
// If the Client's account key is already registered, Email is not used.
Email string
// ForceRSA makes the Manager generate certificates with 2048-bit RSA keys.
//
// If false, a default is used. Currently the default
// is EC-based keys using the P-256 curve.
ForceRSA bool
clientMu sync.Mutex
client *acme.Client // initialized by acmeClient method
stateMu sync.Mutex
state map[string]*certState // keyed by domain name
// tokenCert is keyed by token domain name, which matches server name
// of ClientHello. Keys always have ".acme.invalid" suffix.
tokenCertMu sync.RWMutex
tokenCert map[string]*tls.Certificate
// renewal tracks the set of domains currently running renewal timers.
// It is keyed by domain name.
renewalMu sync.Mutex
renewal map[string]*domainRenewal
}
// GetCertificate implements the tls.Config.GetCertificate hook.
// It provides a TLS certificate for hello.ServerName host, including answering
// *.acme.invalid (TLS-SNI) challenges. All other fields of hello are ignored.
//
// If m.HostPolicy is non-nil, GetCertificate calls the policy before requesting
// a new cert. A non-nil error returned from m.HostPolicy halts TLS negotiation.
// The error is propagated back to the caller of GetCertificate and is user-visible.
// This does not affect cached certs. See HostPolicy field description for more details.
func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
if m.Prompt == nil {
return nil, errors.New("acme/autocert: Manager.Prompt not set")
}
name := hello.ServerName
if name == "" {
return nil, errors.New("acme/autocert: missing server name")
}
if !strings.Contains(strings.Trim(name, "."), ".") {
return nil, errors.New("acme/autocert: server name component count invalid")
}
if strings.ContainsAny(name, `/\`) {
return nil, errors.New("acme/autocert: server name contains invalid character")
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
// check whether this is a token cert requested for TLS-SNI challenge
if strings.HasSuffix(name, ".acme.invalid") {
m.tokenCertMu.RLock()
defer m.tokenCertMu.RUnlock()
if cert := m.tokenCert[name]; cert != nil {
return cert, nil
}
if cert, err := m.cacheGet(ctx, name); err == nil {
return cert, nil
}
// TODO: cache error results?
return nil, fmt.Errorf("acme/autocert: no token cert for %q", name)
}
// regular domain
name = strings.TrimSuffix(name, ".") // golang.org/issue/18114
cert, err := m.cert(ctx, name)
if err == nil {
return cert, nil
}
if err != ErrCacheMiss {
return nil, err
}
// first-time
if err := m.hostPolicy()(ctx, name); err != nil {
return nil, err
}
cert, err = m.createCert(ctx, name)
if err != nil {
return nil, err
}
m.cachePut(ctx, name, cert)
return cert, nil
}
// cert returns an existing certificate either from m.state or cache.
// If a certificate is found in cache but not in m.state, the latter will be filled
// with the cached value.
func (m *Manager) cert(ctx context.Context, name string) (*tls.Certificate, error) {
m.stateMu.Lock()
if s, ok := m.state[name]; ok {
m.stateMu.Unlock()
s.RLock()
defer s.RUnlock()
return s.tlscert()
}
defer m.stateMu.Unlock()
cert, err := m.cacheGet(ctx, name)
if err != nil {
return nil, err
}
signer, ok := cert.PrivateKey.(crypto.Signer)
if !ok {
return nil, errors.New("acme/autocert: private key cannot sign")
}
if m.state == nil {
m.state = make(map[string]*certState)
}
s := &certState{
key: signer,
cert: cert.Certificate,
leaf: cert.Leaf,
}
m.state[name] = s
go m.renew(name, s.key, s.leaf.NotAfter)
return cert, nil
}
// cacheGet always returns a valid certificate, or an error otherwise.
// If a cached certficate exists but is not valid, ErrCacheMiss is returned.
func (m *Manager) cacheGet(ctx context.Context, domain string) (*tls.Certificate, error) {
if m.Cache == nil {
return nil, ErrCacheMiss
}
data, err := m.Cache.Get(ctx, domain)
if err != nil {
return nil, err
}
// private
priv, pub := pem.Decode(data)
if priv == nil || !strings.Contains(priv.Type, "PRIVATE") {
return nil, ErrCacheMiss
}
privKey, err := parsePrivateKey(priv.Bytes)
if err != nil {
return nil, err
}
// public
var pubDER [][]byte
for len(pub) > 0 {
var b *pem.Block
b, pub = pem.Decode(pub)
if b == nil {
break
}
pubDER = append(pubDER, b.Bytes)
}
if len(pub) > 0 {
// Leftover content not consumed by pem.Decode. Corrupt. Ignore.
return nil, ErrCacheMiss
}
// verify and create TLS cert
leaf, err := validCert(domain, pubDER, privKey)
if err != nil {
return nil, ErrCacheMiss
}
tlscert := &tls.Certificate{
Certificate: pubDER,
PrivateKey: privKey,
Leaf: leaf,
}
return tlscert, nil
}
func (m *Manager) cachePut(ctx context.Context, domain string, tlscert *tls.Certificate) error {
if m.Cache == nil {
return nil
}
// contains PEM-encoded data
var buf bytes.Buffer
// private
switch key := tlscert.PrivateKey.(type) {
case *ecdsa.PrivateKey:
if err := encodeECDSAKey(&buf, key); err != nil {
return err
}
case *rsa.PrivateKey:
b := x509.MarshalPKCS1PrivateKey(key)
pb := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: b}
if err := pem.Encode(&buf, pb); err != nil {
return err
}
default:
return errors.New("acme/autocert: unknown private key type")
}
// public
for _, b := range tlscert.Certificate {
pb := &pem.Block{Type: "CERTIFICATE", Bytes: b}
if err := pem.Encode(&buf, pb); err != nil {
return err
}
}
return m.Cache.Put(ctx, domain, buf.Bytes())
}
func encodeECDSAKey(w io.Writer, key *ecdsa.PrivateKey) error {
b, err := x509.MarshalECPrivateKey(key)
if err != nil {
return err
}
pb := &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
return pem.Encode(w, pb)
}
// createCert starts the domain ownership verification and returns a certificate
// for that domain upon success.
//
// If the domain is already being verified, it waits for the existing verification to complete.
// Either way, createCert blocks for the duration of the whole process.
func (m *Manager) createCert(ctx context.Context, domain string) (*tls.Certificate, error) {
// TODO: maybe rewrite this whole piece using sync.Once
state, err := m.certState(domain)
if err != nil {
return nil, err
}
// state may exist if another goroutine is already working on it
// in which case just wait for it to finish
if !state.locked {
state.RLock()
defer state.RUnlock()
return state.tlscert()
}
// We are the first; state is locked.
// Unblock the readers when domain ownership is verified
// and we got the cert or the process failed.
defer state.Unlock()
state.locked = false
der, leaf, err := m.authorizedCert(ctx, state.key, domain)
if err != nil {
// Remove the failed state after some time,
// making the manager call createCert again on the following TLS hello.
time.AfterFunc(createCertRetryAfter, func() {
defer testDidRemoveState(domain)
m.stateMu.Lock()
defer m.stateMu.Unlock()
// Verify the state hasn't changed and it's still invalid
// before deleting.
s, ok := m.state[domain]
if !ok {
return
}
if _, err := validCert(domain, s.cert, s.key); err == nil {
return
}
delete(m.state, domain)
})
return nil, err
}
state.cert = der
state.leaf = leaf
go m.renew(domain, state.key, state.leaf.NotAfter)
return state.tlscert()
}
// certState returns a new or existing certState.
// If a new certState is returned, state.exist is false and the state is locked.
// The returned error is non-nil only in the case where a new state could not be created.
func (m *Manager) certState(domain string) (*certState, error) {
m.stateMu.Lock()
defer m.stateMu.Unlock()
if m.state == nil {
m.state = make(map[string]*certState)
}
// existing state
if state, ok := m.state[domain]; ok {
return state, nil
}
// new locked state
var (
err error
key crypto.Signer
)
if m.ForceRSA {
key, err = rsa.GenerateKey(rand.Reader, 2048)
} else {
key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
}
if err != nil {
return nil, err
}
state := &certState{
key: key,
locked: true,
}
state.Lock() // will be unlocked by m.certState caller
m.state[domain] = state
return state, nil
}
// authorizedCert starts the domain ownership verification process and requests a new cert upon success.
// The key argument is the certificate private key.
func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, domain string) (der [][]byte, leaf *x509.Certificate, err error) {
if err := m.verify(ctx, domain); err != nil {
return nil, nil, err
}
client, err := m.acmeClient(ctx)
if err != nil {
return nil, nil, err
}
csr, err := certRequest(key, domain)
if err != nil {
return nil, nil, err
}
der, _, err = client.CreateCert(ctx, csr, 0, true)
if err != nil {
return nil, nil, err
}
leaf, err = validCert(domain, der, key)
if err != nil {
return nil, nil, err
}
return der, leaf, nil
}
// verify starts a new identifier (domain) authorization flow.
// It prepares a challenge response and then blocks until the authorization
// is marked as "completed" by the CA (either succeeded or failed).
//
// verify returns nil iff the verification was successful.
func (m *Manager) verify(ctx context.Context, domain string) error {
client, err := m.acmeClient(ctx)
if err != nil {
return err
}
// start domain authorization and get the challenge
authz, err := client.Authorize(ctx, domain)
if err != nil {
return err
}
// maybe don't need to at all
if authz.Status == acme.StatusValid {
return nil
}
// pick a challenge: prefer tls-sni-02 over tls-sni-01
// TODO: consider authz.Combinations
var chal *acme.Challenge
for _, c := range authz.Challenges {
if c.Type == "tls-sni-02" {
chal = c
break
}
if c.Type == "tls-sni-01" {
chal = c
}
}
if chal == nil {
return errors.New("acme/autocert: no supported challenge type found")
}
// create a token cert for the challenge response
var (
cert tls.Certificate
name string
)
switch chal.Type {
case "tls-sni-01":
cert, name, err = client.TLSSNI01ChallengeCert(chal.Token)
case "tls-sni-02":
cert, name, err = client.TLSSNI02ChallengeCert(chal.Token)
default:
err = fmt.Errorf("acme/autocert: unknown challenge type %q", chal.Type)
}
if err != nil {
return err
}
m.putTokenCert(ctx, name, &cert)
defer func() {
// verification has ended at this point
// don't need token cert anymore
go m.deleteTokenCert(name)
}()
// ready to fulfill the challenge
if _, err := client.Accept(ctx, chal); err != nil {
return err
}
// wait for the CA to validate
_, err = client.WaitAuthorization(ctx, authz.URI)
return err
}
// putTokenCert stores the cert under the named key in both m.tokenCert map
// and m.Cache.
func (m *Manager) putTokenCert(ctx context.Context, name string, cert *tls.Certificate) {
m.tokenCertMu.Lock()
defer m.tokenCertMu.Unlock()
if m.tokenCert == nil {
m.tokenCert = make(map[string]*tls.Certificate)
}
m.tokenCert[name] = cert
m.cachePut(ctx, name, cert)
}
// deleteTokenCert removes the token certificate for the specified domain name
// from both m.tokenCert map and m.Cache.
func (m *Manager) deleteTokenCert(name string) {
m.tokenCertMu.Lock()
defer m.tokenCertMu.Unlock()
delete(m.tokenCert, name)
if m.Cache != nil {
m.Cache.Delete(context.Background(), name)
}
}
// renew starts a cert renewal timer loop, one per domain.
//
// The loop is scheduled in two cases:
// - a cert was fetched from cache for the first time (wasn't in m.state)
// - a new cert was created by m.createCert
//
// The key argument is a certificate private key.
// The exp argument is the cert expiration time (NotAfter).
func (m *Manager) renew(domain string, key crypto.Signer, exp time.Time) {
m.renewalMu.Lock()
defer m.renewalMu.Unlock()
if m.renewal[domain] != nil {
// another goroutine is already on it
return
}
if m.renewal == nil {
m.renewal = make(map[string]*domainRenewal)
}
dr := &domainRenewal{m: m, domain: domain, key: key}
m.renewal[domain] = dr
dr.start(exp)
}
// stopRenew stops all currently running cert renewal timers.
// The timers are not restarted during the lifetime of the Manager.
func (m *Manager) stopRenew() {
m.renewalMu.Lock()
defer m.renewalMu.Unlock()
for name, dr := range m.renewal {
delete(m.renewal, name)
dr.stop()
}
}
func (m *Manager) accountKey(ctx context.Context) (crypto.Signer, error) {
const keyName = "acme_account.key"
genKey := func() (*ecdsa.PrivateKey, error) {
return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
}
if m.Cache == nil {
return genKey()
}
data, err := m.Cache.Get(ctx, keyName)
if err == ErrCacheMiss {
key, err := genKey()
if err != nil {
return nil, err
}
var buf bytes.Buffer
if err := encodeECDSAKey(&buf, key); err != nil {
return nil, err
}
if err := m.Cache.Put(ctx, keyName, buf.Bytes()); err != nil {
return nil, err
}
return key, nil
}
if err != nil {
return nil, err
}
priv, _ := pem.Decode(data)
if priv == nil || !strings.Contains(priv.Type, "PRIVATE") {
return nil, errors.New("acme/autocert: invalid account key found in cache")
}
return parsePrivateKey(priv.Bytes)
}
func (m *Manager) acmeClient(ctx context.Context) (*acme.Client, error) {
m.clientMu.Lock()
defer m.clientMu.Unlock()
if m.client != nil {
return m.client, nil
}
client := m.Client
if client == nil {
client = &acme.Client{DirectoryURL: acme.LetsEncryptURL}
}
if client.Key == nil {
var err error
client.Key, err = m.accountKey(ctx)
if err != nil {
return nil, err
}
}
var contact []string
if m.Email != "" {
contact = []string{"mailto:" + m.Email}
}
a := &acme.Account{Contact: contact}
_, err := client.Register(ctx, a, m.Prompt)
if ae, ok := err.(*acme.Error); err == nil || ok && ae.StatusCode == http.StatusConflict {
// conflict indicates the key is already registered
m.client = client
err = nil
}
return m.client, err
}
func (m *Manager) hostPolicy() HostPolicy {
if m.HostPolicy != nil {
return m.HostPolicy
}
return defaultHostPolicy
}
func (m *Manager) renewBefore() time.Duration {
if m.RenewBefore > renewJitter {
return m.RenewBefore
}
return 720 * time.Hour // 30 days
}
// certState is ready when its mutex is unlocked for reading.
type certState struct {
sync.RWMutex
locked bool // locked for read/write
key crypto.Signer // private key for cert
cert [][]byte // DER encoding
leaf *x509.Certificate // parsed cert[0]; always non-nil if cert != nil
}
// tlscert creates a tls.Certificate from s.key and s.cert.
// Callers should wrap it in s.RLock() and s.RUnlock().
func (s *certState) tlscert() (*tls.Certificate, error) {
if s.key == nil {
return nil, errors.New("acme/autocert: missing signer")
}
if len(s.cert) == 0 {
return nil, errors.New("acme/autocert: missing certificate")
}
return &tls.Certificate{
PrivateKey: s.key,
Certificate: s.cert,
Leaf: s.leaf,
}, nil
}
// certRequest creates a certificate request for the given common name cn
// and optional SANs.
func certRequest(key crypto.Signer, cn string, san ...string) ([]byte, error) {
req := &x509.CertificateRequest{
Subject: pkix.Name{CommonName: cn},
DNSNames: san,
}
return x509.CreateCertificateRequest(rand.Reader, req, key)
}
// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates
// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys.
// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three.
//
// Inspired by parsePrivateKey in crypto/tls/tls.go.
func parsePrivateKey(der []byte) (crypto.Signer, error) {
if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
return key, nil
}
if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
switch key := key.(type) {
case *rsa.PrivateKey:
return key, nil
case *ecdsa.PrivateKey:
return key, nil
default:
return nil, errors.New("acme/autocert: unknown private key type in PKCS#8 wrapping")
}
}
if key, err := x509.ParseECPrivateKey(der); err == nil {
return key, nil
}
return nil, errors.New("acme/autocert: failed to parse private key")
}
// validCert parses a cert chain provided as der argument and verifies the leaf, der[0],
// corresponds to the private key, as well as the domain match and expiration dates.
// It doesn't do any revocation checking.
//
// The returned value is the verified leaf cert.
func validCert(domain string, der [][]byte, key crypto.Signer) (leaf *x509.Certificate, err error) {
// parse public part(s)
var n int
for _, b := range der {
n += len(b)
}
pub := make([]byte, n)
n = 0
for _, b := range der {
n += copy(pub[n:], b)
}
x509Cert, err := x509.ParseCertificates(pub)
if len(x509Cert) == 0 {
return nil, errors.New("acme/autocert: no public key found")
}
// verify the leaf is not expired and matches the domain name
leaf = x509Cert[0]
now := timeNow()
if now.Before(leaf.NotBefore) {
return nil, errors.New("acme/autocert: certificate is not valid yet")
}
if now.After(leaf.NotAfter) {
return nil, errors.New("acme/autocert: expired certificate")
}
if err := leaf.VerifyHostname(domain); err != nil {
return nil, err
}
// ensure the leaf corresponds to the private key
switch pub := leaf.PublicKey.(type) {
case *rsa.PublicKey:
prv, ok := key.(*rsa.PrivateKey)
if !ok {
return nil, errors.New("acme/autocert: private key type does not match public key type")
}
if pub.N.Cmp(prv.N) != 0 {
return nil, errors.New("acme/autocert: private key does not match public key")
}
case *ecdsa.PublicKey:
prv, ok := key.(*ecdsa.PrivateKey)
if !ok {
return nil, errors.New("acme/autocert: private key type does not match public key type")
}
if pub.X.Cmp(prv.X) != 0 || pub.Y.Cmp(prv.Y) != 0 {
return nil, errors.New("acme/autocert: private key does not match public key")
}
default:
return nil, errors.New("acme/autocert: unknown public key algorithm")
}
return leaf, nil
}
func retryAfter(v string) time.Duration {
if i, err := strconv.Atoi(v); err == nil {
return time.Duration(i) * time.Second
}
if t, err := http.ParseTime(v); err == nil {
return t.Sub(timeNow())
}
return time.Second
}
type lockedMathRand struct {
sync.Mutex
rnd *mathrand.Rand
}
func (r *lockedMathRand) int63n(max int64) int64 {
r.Lock()
n := r.rnd.Int63n(max)
r.Unlock()
return n
}
// For easier testing.
var (
timeNow = time.Now
// Called when a state is removed.
testDidRemoveState = func(domain string) {}
)

606
vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,606 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package autocert
import (
"context"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/base64"
"encoding/json"
"fmt"
"html/template"
"io"
"math/big"
"net/http"
"net/http/httptest"
"reflect"
"sync"
"testing"
"time"
"golang.org/x/crypto/acme"
)
var discoTmpl = template.Must(template.New("disco").Parse(`{
"new-reg": "{{.}}/new-reg",
"new-authz": "{{.}}/new-authz",
"new-cert": "{{.}}/new-cert"
}`))
var authzTmpl = template.Must(template.New("authz").Parse(`{
"status": "pending",
"challenges": [
{
"uri": "{{.}}/challenge/1",
"type": "tls-sni-01",
"token": "token-01"
},
{
"uri": "{{.}}/challenge/2",
"type": "tls-sni-02",
"token": "token-02"
}
]
}`))
type memCache struct {
mu sync.Mutex
keyData map[string][]byte
}
func (m *memCache) Get(ctx context.Context, key string) ([]byte, error) {
m.mu.Lock()
defer m.mu.Unlock()
v, ok := m.keyData[key]
if !ok {
return nil, ErrCacheMiss
}
return v, nil
}
func (m *memCache) Put(ctx context.Context, key string, data []byte) error {
m.mu.Lock()
defer m.mu.Unlock()
m.keyData[key] = data
return nil
}
func (m *memCache) Delete(ctx context.Context, key string) error {
m.mu.Lock()
defer m.mu.Unlock()
delete(m.keyData, key)
return nil
}
func newMemCache() *memCache {
return &memCache{
keyData: make(map[string][]byte),
}
}
func dummyCert(pub interface{}, san ...string) ([]byte, error) {
return dateDummyCert(pub, time.Now(), time.Now().Add(90*24*time.Hour), san...)
}
func dateDummyCert(pub interface{}, start, end time.Time, san ...string) ([]byte, error) {
// use EC key to run faster on 386
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, err
}
t := &x509.Certificate{
SerialNumber: big.NewInt(1),
NotBefore: start,
NotAfter: end,
BasicConstraintsValid: true,
KeyUsage: x509.KeyUsageKeyEncipherment,
DNSNames: san,
}
if pub == nil {
pub = &key.PublicKey
}
return x509.CreateCertificate(rand.Reader, t, t, pub, key)
}
func decodePayload(v interface{}, r io.Reader) error {
var req struct{ Payload string }
if err := json.NewDecoder(r).Decode(&req); err != nil {
return err
}
payload, err := base64.RawURLEncoding.DecodeString(req.Payload)
if err != nil {
return err
}
return json.Unmarshal(payload, v)
}
func TestGetCertificate(t *testing.T) {
man := &Manager{Prompt: AcceptTOS}
defer man.stopRenew()
hello := &tls.ClientHelloInfo{ServerName: "example.org"}
testGetCertificate(t, man, "example.org", hello)
}
func TestGetCertificate_trailingDot(t *testing.T) {
man := &Manager{Prompt: AcceptTOS}
defer man.stopRenew()
hello := &tls.ClientHelloInfo{ServerName: "example.org."}
testGetCertificate(t, man, "example.org", hello)
}
func TestGetCertificate_ForceRSA(t *testing.T) {
man := &Manager{
Prompt: AcceptTOS,
Cache: newMemCache(),
ForceRSA: true,
}
defer man.stopRenew()
hello := &tls.ClientHelloInfo{ServerName: "example.org"}
testGetCertificate(t, man, "example.org", hello)
cert, err := man.cacheGet(context.Background(), "example.org")
if err != nil {
t.Fatalf("man.cacheGet: %v", err)
}
if _, ok := cert.PrivateKey.(*rsa.PrivateKey); !ok {
t.Errorf("cert.PrivateKey is %T; want *rsa.PrivateKey", cert.PrivateKey)
}
}
func TestGetCertificate_nilPrompt(t *testing.T) {
man := &Manager{}
defer man.stopRenew()
url, finish := startACMEServerStub(t, man, "example.org")
defer finish()
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
t.Fatal(err)
}
man.Client = &acme.Client{
Key: key,
DirectoryURL: url,
}
hello := &tls.ClientHelloInfo{ServerName: "example.org"}
if _, err := man.GetCertificate(hello); err == nil {
t.Error("got certificate for example.org; wanted error")
}
}
func TestGetCertificate_expiredCache(t *testing.T) {
// Make an expired cert and cache it.
pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
t.Fatal(err)
}
tmpl := &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{CommonName: "example.org"},
NotAfter: time.Now(),
}
pub, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &pk.PublicKey, pk)
if err != nil {
t.Fatal(err)
}
tlscert := &tls.Certificate{
Certificate: [][]byte{pub},
PrivateKey: pk,
}
man := &Manager{Prompt: AcceptTOS, Cache: newMemCache()}
defer man.stopRenew()
if err := man.cachePut(context.Background(), "example.org", tlscert); err != nil {
t.Fatalf("man.cachePut: %v", err)
}
// The expired cached cert should trigger a new cert issuance
// and return without an error.
hello := &tls.ClientHelloInfo{ServerName: "example.org"}
testGetCertificate(t, man, "example.org", hello)
}
func TestGetCertificate_failedAttempt(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadRequest)
}))
defer ts.Close()
const example = "example.org"
d := createCertRetryAfter
f := testDidRemoveState
defer func() {
createCertRetryAfter = d
testDidRemoveState = f
}()
createCertRetryAfter = 0
done := make(chan struct{})
testDidRemoveState = func(domain string) {
if domain != example {
t.Errorf("testDidRemoveState: domain = %q; want %q", domain, example)
}
close(done)
}
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
t.Fatal(err)
}
man := &Manager{
Prompt: AcceptTOS,
Client: &acme.Client{
Key: key,
DirectoryURL: ts.URL,
},
}
defer man.stopRenew()
hello := &tls.ClientHelloInfo{ServerName: example}
if _, err := man.GetCertificate(hello); err == nil {
t.Error("GetCertificate: err is nil")
}
select {
case <-time.After(5 * time.Second):
t.Errorf("took too long to remove the %q state", example)
case <-done:
man.stateMu.Lock()
defer man.stateMu.Unlock()
if v, exist := man.state[example]; exist {
t.Errorf("state exists for %q: %+v", example, v)
}
}
}
// startACMEServerStub runs an ACME server
// The domain argument is the expected domain name of a certificate request.
func startACMEServerStub(t *testing.T, man *Manager, domain string) (url string, finish func()) {
// echo token-02 | shasum -a 256
// then divide result in 2 parts separated by dot
tokenCertName := "4e8eb87631187e9ff2153b56b13a4dec.13a35d002e485d60ff37354b32f665d9.token.acme.invalid"
verifyTokenCert := func() {
hello := &tls.ClientHelloInfo{ServerName: tokenCertName}
_, err := man.GetCertificate(hello)
if err != nil {
t.Errorf("verifyTokenCert: GetCertificate(%q): %v", tokenCertName, err)
return
}
}
// ACME CA server stub
var ca *httptest.Server
ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Replay-Nonce", "nonce")
if r.Method == "HEAD" {
// a nonce request
return
}
switch r.URL.Path {
// discovery
case "/":
if err := discoTmpl.Execute(w, ca.URL); err != nil {
t.Errorf("discoTmpl: %v", err)
}
// client key registration
case "/new-reg":
w.Write([]byte("{}"))
// domain authorization
case "/new-authz":
w.Header().Set("Location", ca.URL+"/authz/1")
w.WriteHeader(http.StatusCreated)
if err := authzTmpl.Execute(w, ca.URL); err != nil {
t.Errorf("authzTmpl: %v", err)
}
// accept tls-sni-02 challenge
case "/challenge/2":
verifyTokenCert()
w.Write([]byte("{}"))
// authorization status
case "/authz/1":
w.Write([]byte(`{"status": "valid"}`))
// cert request
case "/new-cert":
var req struct {
CSR string `json:"csr"`
}
decodePayload(&req, r.Body)
b, _ := base64.RawURLEncoding.DecodeString(req.CSR)
csr, err := x509.ParseCertificateRequest(b)
if err != nil {
t.Errorf("new-cert: CSR: %v", err)
}
if csr.Subject.CommonName != domain {
t.Errorf("CommonName in CSR = %q; want %q", csr.Subject.CommonName, domain)
}
der, err := dummyCert(csr.PublicKey, domain)
if err != nil {
t.Errorf("new-cert: dummyCert: %v", err)
}
chainUp := fmt.Sprintf("<%s/ca-cert>; rel=up", ca.URL)
w.Header().Set("Link", chainUp)
w.WriteHeader(http.StatusCreated)
w.Write(der)
// CA chain cert
case "/ca-cert":
der, err := dummyCert(nil, "ca")
if err != nil {
t.Errorf("ca-cert: dummyCert: %v", err)
}
w.Write(der)
default:
t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path)
}
}))
finish = func() {
ca.Close()
// make sure token cert was removed
cancel := make(chan struct{})
done := make(chan struct{})
go func() {
defer close(done)
tick := time.NewTicker(100 * time.Millisecond)
defer tick.Stop()
for {
hello := &tls.ClientHelloInfo{ServerName: tokenCertName}
if _, err := man.GetCertificate(hello); err != nil {
return
}
select {
case <-tick.C:
case <-cancel:
return
}
}
}()
select {
case <-done:
case <-time.After(5 * time.Second):
close(cancel)
t.Error("token cert was not removed")
<-done
}
}
return ca.URL, finish
}
// tests man.GetCertificate flow using the provided hello argument.
// The domain argument is the expected domain name of a certificate request.
func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.ClientHelloInfo) {
url, finish := startACMEServerStub(t, man, domain)
defer finish()
// use EC key to run faster on 386
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
t.Fatal(err)
}
man.Client = &acme.Client{
Key: key,
DirectoryURL: url,
}
// simulate tls.Config.GetCertificate
var tlscert *tls.Certificate
done := make(chan struct{})
go func() {
tlscert, err = man.GetCertificate(hello)
close(done)
}()
select {
case <-time.After(time.Minute):
t.Fatal("man.GetCertificate took too long to return")
case <-done:
}
if err != nil {
t.Fatalf("man.GetCertificate: %v", err)
}
// verify the tlscert is the same we responded with from the CA stub
if len(tlscert.Certificate) == 0 {
t.Fatal("len(tlscert.Certificate) is 0")
}
cert, err := x509.ParseCertificate(tlscert.Certificate[0])
if err != nil {
t.Fatalf("x509.ParseCertificate: %v", err)
}
if len(cert.DNSNames) == 0 || cert.DNSNames[0] != domain {
t.Errorf("cert.DNSNames = %v; want %q", cert.DNSNames, domain)
}
}
func TestAccountKeyCache(t *testing.T) {
m := Manager{Cache: newMemCache()}
ctx := context.Background()
k1, err := m.accountKey(ctx)
if err != nil {
t.Fatal(err)
}
k2, err := m.accountKey(ctx)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(k1, k2) {
t.Errorf("account keys don't match: k1 = %#v; k2 = %#v", k1, k2)
}
}
func TestCache(t *testing.T) {
privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
t.Fatal(err)
}
tmpl := &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{CommonName: "example.org"},
NotAfter: time.Now().Add(time.Hour),
}
pub, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &privKey.PublicKey, privKey)
if err != nil {
t.Fatal(err)
}
tlscert := &tls.Certificate{
Certificate: [][]byte{pub},
PrivateKey: privKey,
}
man := &Manager{Cache: newMemCache()}
defer man.stopRenew()
ctx := context.Background()
if err := man.cachePut(ctx, "example.org", tlscert); err != nil {
t.Fatalf("man.cachePut: %v", err)
}
res, err := man.cacheGet(ctx, "example.org")
if err != nil {
t.Fatalf("man.cacheGet: %v", err)
}
if res == nil {
t.Fatal("res is nil")
}
}
func TestHostWhitelist(t *testing.T) {
policy := HostWhitelist("example.com", "example.org", "*.example.net")
tt := []struct {
host string
allow bool
}{
{"example.com", true},
{"example.org", true},
{"one.example.com", false},
{"two.example.org", false},
{"three.example.net", false},
{"dummy", false},
}
for i, test := range tt {
err := policy(nil, test.host)
if err != nil && test.allow {
t.Errorf("%d: policy(%q): %v; want nil", i, test.host, err)
}
if err == nil && !test.allow {
t.Errorf("%d: policy(%q): nil; want an error", i, test.host)
}
}
}
func TestValidCert(t *testing.T) {
key1, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
t.Fatal(err)
}
key2, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
t.Fatal(err)
}
key3, err := rsa.GenerateKey(rand.Reader, 512)
if err != nil {
t.Fatal(err)
}
cert1, err := dummyCert(key1.Public(), "example.org")
if err != nil {
t.Fatal(err)
}
cert2, err := dummyCert(key2.Public(), "example.org")
if err != nil {
t.Fatal(err)
}
cert3, err := dummyCert(key3.Public(), "example.org")
if err != nil {
t.Fatal(err)
}
now := time.Now()
early, err := dateDummyCert(key1.Public(), now.Add(time.Hour), now.Add(2*time.Hour), "example.org")
if err != nil {
t.Fatal(err)
}
expired, err := dateDummyCert(key1.Public(), now.Add(-2*time.Hour), now.Add(-time.Hour), "example.org")
if err != nil {
t.Fatal(err)
}
tt := []struct {
domain string
key crypto.Signer
cert [][]byte
ok bool
}{
{"example.org", key1, [][]byte{cert1}, true},
{"example.org", key3, [][]byte{cert3}, true},
{"example.org", key1, [][]byte{cert1, cert2, cert3}, true},
{"example.org", key1, [][]byte{cert1, {1}}, false},
{"example.org", key1, [][]byte{{1}}, false},
{"example.org", key1, [][]byte{cert2}, false},
{"example.org", key2, [][]byte{cert1}, false},
{"example.org", key1, [][]byte{cert3}, false},
{"example.org", key3, [][]byte{cert1}, false},
{"example.net", key1, [][]byte{cert1}, false},
{"example.org", key1, [][]byte{early}, false},
{"example.org", key1, [][]byte{expired}, false},
}
for i, test := range tt {
leaf, err := validCert(test.domain, test.cert, test.key)
if err != nil && test.ok {
t.Errorf("%d: err = %v", i, err)
}
if err == nil && !test.ok {
t.Errorf("%d: err is nil", i)
}
if err == nil && test.ok && leaf == nil {
t.Errorf("%d: leaf is nil", i)
}
}
}
type cacheGetFunc func(ctx context.Context, key string) ([]byte, error)
func (f cacheGetFunc) Get(ctx context.Context, key string) ([]byte, error) {
return f(ctx, key)
}
func (f cacheGetFunc) Put(ctx context.Context, key string, data []byte) error {
return fmt.Errorf("unsupported Put of %q = %q", key, data)
}
func (f cacheGetFunc) Delete(ctx context.Context, key string) error {
return fmt.Errorf("unsupported Delete of %q", key)
}
func TestManagerGetCertificateBogusSNI(t *testing.T) {
m := Manager{
Prompt: AcceptTOS,
Cache: cacheGetFunc(func(ctx context.Context, key string) ([]byte, error) {
return nil, fmt.Errorf("cache.Get of %s", key)
}),
}
tests := []struct {
name string
wantErr string
}{
{"foo.com", "cache.Get of foo.com"},
{"foo.com.", "cache.Get of foo.com"},
{`a\b.com`, "acme/autocert: server name contains invalid character"},
{`a/b.com`, "acme/autocert: server name contains invalid character"},
{"", "acme/autocert: missing server name"},
{"foo", "acme/autocert: server name component count invalid"},
{".foo", "acme/autocert: server name component count invalid"},
{"foo.", "acme/autocert: server name component count invalid"},
{"fo.o", "cache.Get of fo.o"},
}
for _, tt := range tests {
_, err := m.GetCertificate(&tls.ClientHelloInfo{ServerName: tt.name})
got := fmt.Sprint(err)
if got != tt.wantErr {
t.Errorf("GetCertificate(SNI = %q) = %q; want %q", tt.name, got, tt.wantErr)
}
}
}

130
vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/cache.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,130 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package autocert
import (
"context"
"errors"
"io/ioutil"
"os"
"path/filepath"
)
// ErrCacheMiss is returned when a certificate is not found in cache.
var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss")
// Cache is used by Manager to store and retrieve previously obtained certificates
// as opaque data.
//
// The key argument of the methods refers to a domain name but need not be an FQDN.
// Cache implementations should not rely on the key naming pattern.
type Cache interface {
// Get returns a certificate data for the specified key.
// If there's no such key, Get returns ErrCacheMiss.
Get(ctx context.Context, key string) ([]byte, error)
// Put stores the data in the cache under the specified key.
// Underlying implementations may use any data storage format,
// as long as the reverse operation, Get, results in the original data.
Put(ctx context.Context, key string, data []byte) error
// Delete removes a certificate data from the cache under the specified key.
// If there's no such key in the cache, Delete returns nil.
Delete(ctx context.Context, key string) error
}
// DirCache implements Cache using a directory on the local filesystem.
// If the directory does not exist, it will be created with 0700 permissions.
type DirCache string
// Get reads a certificate data from the specified file name.
func (d DirCache) Get(ctx context.Context, name string) ([]byte, error) {
name = filepath.Join(string(d), name)
var (
data []byte
err error
done = make(chan struct{})
)
go func() {
data, err = ioutil.ReadFile(name)
close(done)
}()
select {
case <-ctx.Done():
return nil, ctx.Err()
case <-done:
}
if os.IsNotExist(err) {
return nil, ErrCacheMiss
}
return data, err
}
// Put writes the certificate data to the specified file name.
// The file will be created with 0600 permissions.
func (d DirCache) Put(ctx context.Context, name string, data []byte) error {
if err := os.MkdirAll(string(d), 0700); err != nil {
return err
}
done := make(chan struct{})
var err error
go func() {
defer close(done)
var tmp string
if tmp, err = d.writeTempFile(name, data); err != nil {
return
}
select {
case <-ctx.Done():
// Don't overwrite the file if the context was canceled.
default:
newName := filepath.Join(string(d), name)
err = os.Rename(tmp, newName)
}
}()
select {
case <-ctx.Done():
return ctx.Err()
case <-done:
}
return err
}
// Delete removes the specified file name.
func (d DirCache) Delete(ctx context.Context, name string) error {
name = filepath.Join(string(d), name)
var (
err error
done = make(chan struct{})
)
go func() {
err = os.Remove(name)
close(done)
}()
select {
case <-ctx.Done():
return ctx.Err()
case <-done:
}
if err != nil && !os.IsNotExist(err) {
return err
}
return nil
}
// writeTempFile writes b to a temporary file, closes the file and returns its path.
func (d DirCache) writeTempFile(prefix string, b []byte) (string, error) {
// TempFile uses 0600 permissions
f, err := ioutil.TempFile(string(d), prefix)
if err != nil {
return "", err
}
if _, err := f.Write(b); err != nil {
f.Close()
return "", err
}
return f.Name(), f.Close()
}

58
vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/cache_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,58 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package autocert
import (
"context"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"testing"
)
// make sure DirCache satisfies Cache interface
var _ Cache = DirCache("/")
func TestDirCache(t *testing.T) {
dir, err := ioutil.TempDir("", "autocert")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
dir = filepath.Join(dir, "certs") // a nonexistent dir
cache := DirCache(dir)
ctx := context.Background()
// test cache miss
if _, err := cache.Get(ctx, "nonexistent"); err != ErrCacheMiss {
t.Errorf("get: %v; want ErrCacheMiss", err)
}
// test put/get
b1 := []byte{1}
if err := cache.Put(ctx, "dummy", b1); err != nil {
t.Fatalf("put: %v", err)
}
b2, err := cache.Get(ctx, "dummy")
if err != nil {
t.Fatalf("get: %v", err)
}
if !reflect.DeepEqual(b1, b2) {
t.Errorf("b1 = %v; want %v", b1, b2)
}
name := filepath.Join(dir, "dummy")
if _, err := os.Stat(name); err != nil {
t.Error(err)
}
// test delete
if err := cache.Delete(ctx, "dummy"); err != nil {
t.Fatalf("delete: %v", err)
}
if _, err := cache.Get(ctx, "dummy"); err != ErrCacheMiss {
t.Errorf("get: %v; want ErrCacheMiss", err)
}
}

35
vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/example_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,35 @@
// Copyright 2017 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.
package autocert_test
import (
"crypto/tls"
"fmt"
"log"
"net/http"
"golang.org/x/crypto/acme/autocert"
)
func ExampleNewListener() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, TLS user! Your config: %+v", r.TLS)
})
log.Fatal(http.Serve(autocert.NewListener("example.com"), mux))
}
func ExampleManager() {
m := autocert.Manager{
Cache: autocert.DirCache("secret-dir"),
Prompt: autocert.AcceptTOS,
HostPolicy: autocert.HostWhitelist("example.org"),
}
s := &http.Server{
Addr: ":https",
TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
}
s.ListenAndServeTLS("", "")
}

160
vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/listener.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,160 @@
// Copyright 2017 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.
package autocert
import (
"crypto/tls"
"log"
"net"
"os"
"path/filepath"
"runtime"
"time"
)
// NewListener returns a net.Listener that listens on the standard TLS
// port (443) on all interfaces and returns *tls.Conn connections with
// LetsEncrypt certificates for the provided domain or domains.
//
// It enables one-line HTTPS servers:
//
// log.Fatal(http.Serve(autocert.NewListener("example.com"), handler))
//
// NewListener is a convenience function for a common configuration.
// More complex or custom configurations can use the autocert.Manager
// type instead.
//
// Use of this function implies acceptance of the LetsEncrypt Terms of
// Service. If domains is not empty, the provided domains are passed
// to HostWhitelist. If domains is empty, the listener will do
// LetsEncrypt challenges for any requested domain, which is not
// recommended.
//
// Certificates are cached in a "golang-autocert" directory under an
// operating system-specific cache or temp directory. This may not
// be suitable for servers spanning multiple machines.
//
// The returned listener uses a *tls.Config that enables HTTP/2, and
// should only be used with servers that support HTTP/2.
//
// The returned Listener also enables TCP keep-alives on the accepted
// connections. The returned *tls.Conn are returned before their TLS
// handshake has completed.
func NewListener(domains ...string) net.Listener {
m := &Manager{
Prompt: AcceptTOS,
}
if len(domains) > 0 {
m.HostPolicy = HostWhitelist(domains...)
}
dir := cacheDir()
if err := os.MkdirAll(dir, 0700); err != nil {
log.Printf("warning: autocert.NewListener not using a cache: %v", err)
} else {
m.Cache = DirCache(dir)
}
return m.Listener()
}
// Listener listens on the standard TLS port (443) on all interfaces
// and returns a net.Listener returning *tls.Conn connections.
//
// The returned listener uses a *tls.Config that enables HTTP/2, and
// should only be used with servers that support HTTP/2.
//
// The returned Listener also enables TCP keep-alives on the accepted
// connections. The returned *tls.Conn are returned before their TLS
// handshake has completed.
//
// Unlike NewListener, it is the caller's responsibility to initialize
// the Manager m's Prompt, Cache, HostPolicy, and other desired options.
func (m *Manager) Listener() net.Listener {
ln := &listener{
m: m,
conf: &tls.Config{
GetCertificate: m.GetCertificate, // bonus: panic on nil m
NextProtos: []string{"h2", "http/1.1"}, // Enable HTTP/2
},
}
ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443")
return ln
}
type listener struct {
m *Manager
conf *tls.Config
tcpListener net.Listener
tcpListenErr error
}
func (ln *listener) Accept() (net.Conn, error) {
if ln.tcpListenErr != nil {
return nil, ln.tcpListenErr
}
conn, err := ln.tcpListener.Accept()
if err != nil {
return nil, err
}
tcpConn := conn.(*net.TCPConn)
// Because Listener is a convenience function, help out with
// this too. This is not possible for the caller to set once
// we return a *tcp.Conn wrapping an inaccessible net.Conn.
// If callers don't want this, they can do things the manual
// way and tweak as needed. But this is what net/http does
// itself, so copy that. If net/http changes, we can change
// here too.
tcpConn.SetKeepAlive(true)
tcpConn.SetKeepAlivePeriod(3 * time.Minute)
return tls.Server(tcpConn, ln.conf), nil
}
func (ln *listener) Addr() net.Addr {
if ln.tcpListener != nil {
return ln.tcpListener.Addr()
}
// net.Listen failed. Return something non-nil in case callers
// call Addr before Accept:
return &net.TCPAddr{IP: net.IP{0, 0, 0, 0}, Port: 443}
}
func (ln *listener) Close() error {
if ln.tcpListenErr != nil {
return ln.tcpListenErr
}
return ln.tcpListener.Close()
}
func homeDir() string {
if runtime.GOOS == "windows" {
return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
}
if h := os.Getenv("HOME"); h != "" {
return h
}
return "/"
}
func cacheDir() string {
const base = "golang-autocert"
switch runtime.GOOS {
case "darwin":
return filepath.Join(homeDir(), "Library", "Caches", base)
case "windows":
for _, ev := range []string{"APPDATA", "CSIDL_APPDATA", "TEMP", "TMP"} {
if v := os.Getenv(ev); v != "" {
return filepath.Join(v, base)
}
}
// Worst case:
return filepath.Join(homeDir(), base)
}
if xdg := os.Getenv("XDG_CACHE_HOME"); xdg != "" {
return filepath.Join(xdg, base)
}
return filepath.Join(homeDir(), ".cache", base)
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше