Updating golang dependancies (#4075)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
6d62d65b2d
Коммит
2ca0e8f9a0
944
vendor/golang.org/x/crypto/acme/acme.go
сгенерированный
поставляемый
Обычный файл
944
vendor/golang.org/x/crypto/acme/acme.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,944 @@
|
||||
// Copyright 2015 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 acme provides an implementation of the
|
||||
// Automatic Certificate Management Environment (ACME) spec.
|
||||
// See https://tools.ietf.org/html/draft-ietf-acme-acme-02 for details.
|
||||
//
|
||||
// Most common scenarios will want to use autocert subdirectory instead,
|
||||
// which 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 acme
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/net/context/ctxhttp"
|
||||
)
|
||||
|
||||
// LetsEncryptURL is the Directory endpoint of Let's Encrypt CA.
|
||||
const LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory"
|
||||
|
||||
const (
|
||||
maxChainLen = 5 // max depth and breadth of a certificate chain
|
||||
maxCertSize = 1 << 20 // max size of a certificate, in bytes
|
||||
)
|
||||
|
||||
// CertOption is an optional argument type for Client methods which manipulate
|
||||
// certificate data.
|
||||
type CertOption interface {
|
||||
privateCertOpt()
|
||||
}
|
||||
|
||||
// WithKey creates an option holding a private/public key pair.
|
||||
// The private part signs a certificate, and the public part represents the signee.
|
||||
func WithKey(key crypto.Signer) CertOption {
|
||||
return &certOptKey{key}
|
||||
}
|
||||
|
||||
type certOptKey struct {
|
||||
key crypto.Signer
|
||||
}
|
||||
|
||||
func (*certOptKey) privateCertOpt() {}
|
||||
|
||||
// WithTemplate creates an option for specifying a certificate template.
|
||||
// See x509.CreateCertificate for template usage details.
|
||||
//
|
||||
// In TLSSNIxChallengeCert methods, the template is also used as parent,
|
||||
// resulting in a self-signed certificate.
|
||||
// The DNSNames field of t is always overwritten for tls-sni challenge certs.
|
||||
func WithTemplate(t *x509.Certificate) CertOption {
|
||||
return (*certOptTemplate)(t)
|
||||
}
|
||||
|
||||
type certOptTemplate x509.Certificate
|
||||
|
||||
func (*certOptTemplate) privateCertOpt() {}
|
||||
|
||||
// Client is an ACME client.
|
||||
// The only required field is Key. An example of creating a client with a new key
|
||||
// is as follows:
|
||||
//
|
||||
// key, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
// client := &Client{Key: key}
|
||||
//
|
||||
type Client struct {
|
||||
// Key is the account key used to register with a CA and sign requests.
|
||||
// Key.Public() must return a *rsa.PublicKey or *ecdsa.PublicKey.
|
||||
Key crypto.Signer
|
||||
|
||||
// HTTPClient optionally specifies an HTTP client to use
|
||||
// instead of http.DefaultClient.
|
||||
HTTPClient *http.Client
|
||||
|
||||
// DirectoryURL points to the CA directory endpoint.
|
||||
// If empty, LetsEncryptURL is used.
|
||||
// Mutating this value after a successful call of Client's Discover method
|
||||
// will have no effect.
|
||||
DirectoryURL string
|
||||
|
||||
dirMu sync.Mutex // guards writes to dir
|
||||
dir *Directory // cached result of Client's Discover method
|
||||
}
|
||||
|
||||
// Discover performs ACME server discovery using c.DirectoryURL.
|
||||
//
|
||||
// It caches successful result. So, subsequent calls will not result in
|
||||
// a network round-trip. This also means mutating c.DirectoryURL after successful call
|
||||
// of this method will have no effect.
|
||||
func (c *Client) Discover(ctx context.Context) (Directory, error) {
|
||||
c.dirMu.Lock()
|
||||
defer c.dirMu.Unlock()
|
||||
if c.dir != nil {
|
||||
return *c.dir, nil
|
||||
}
|
||||
|
||||
dirURL := c.DirectoryURL
|
||||
if dirURL == "" {
|
||||
dirURL = LetsEncryptURL
|
||||
}
|
||||
res, err := ctxhttp.Get(ctx, c.HTTPClient, dirURL)
|
||||
if err != nil {
|
||||
return Directory{}, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return Directory{}, responseError(res)
|
||||
}
|
||||
|
||||
var v struct {
|
||||
Reg string `json:"new-reg"`
|
||||
Authz string `json:"new-authz"`
|
||||
Cert string `json:"new-cert"`
|
||||
Revoke string `json:"revoke-cert"`
|
||||
Meta struct {
|
||||
Terms string `json:"terms-of-service"`
|
||||
Website string `json:"website"`
|
||||
CAA []string `json:"caa-identities"`
|
||||
}
|
||||
}
|
||||
if json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||
return Directory{}, err
|
||||
}
|
||||
c.dir = &Directory{
|
||||
RegURL: v.Reg,
|
||||
AuthzURL: v.Authz,
|
||||
CertURL: v.Cert,
|
||||
RevokeURL: v.Revoke,
|
||||
Terms: v.Meta.Terms,
|
||||
Website: v.Meta.Website,
|
||||
CAA: v.Meta.CAA,
|
||||
}
|
||||
return *c.dir, nil
|
||||
}
|
||||
|
||||
// CreateCert requests a new certificate using the Certificate Signing Request csr encoded in DER format.
|
||||
// The exp argument indicates the desired certificate validity duration. CA may issue a certificate
|
||||
// with a different duration.
|
||||
// If the bundle argument is true, the returned value will also contain the CA (issuer) certificate chain.
|
||||
//
|
||||
// In the case where CA server does not provide the issued certificate in the response,
|
||||
// CreateCert will poll certURL using c.FetchCert, which will result in additional round-trips.
|
||||
// In such scenario the caller can cancel the polling with ctx.
|
||||
//
|
||||
// CreateCert returns an error if the CA's response or chain was unreasonably large.
|
||||
// Callers are encouraged to parse the returned value to ensure the certificate is valid and has the expected features.
|
||||
func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, bundle bool) (der [][]byte, certURL string, err error) {
|
||||
if _, err := c.Discover(ctx); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
req := struct {
|
||||
Resource string `json:"resource"`
|
||||
CSR string `json:"csr"`
|
||||
NotBefore string `json:"notBefore,omitempty"`
|
||||
NotAfter string `json:"notAfter,omitempty"`
|
||||
}{
|
||||
Resource: "new-cert",
|
||||
CSR: base64.RawURLEncoding.EncodeToString(csr),
|
||||
}
|
||||
now := timeNow()
|
||||
req.NotBefore = now.Format(time.RFC3339)
|
||||
if exp > 0 {
|
||||
req.NotAfter = now.Add(exp).Format(time.RFC3339)
|
||||
}
|
||||
|
||||
res, err := postJWS(ctx, c.HTTPClient, c.Key, c.dir.CertURL, req)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusCreated {
|
||||
return nil, "", responseError(res)
|
||||
}
|
||||
|
||||
curl := res.Header.Get("location") // cert permanent URL
|
||||
if res.ContentLength == 0 {
|
||||
// no cert in the body; poll until we get it
|
||||
cert, err := c.FetchCert(ctx, curl, bundle)
|
||||
return cert, curl, err
|
||||
}
|
||||
// slurp issued cert and CA chain, if requested
|
||||
cert, err := responseCert(ctx, c.HTTPClient, res, bundle)
|
||||
return cert, curl, err
|
||||
}
|
||||
|
||||
// FetchCert retrieves already issued certificate from the given url, in DER format.
|
||||
// It retries the request until the certificate is successfully retrieved,
|
||||
// context is cancelled by the caller or an error response is received.
|
||||
//
|
||||
// The returned value will also contain the CA (issuer) certificate if the bundle argument is true.
|
||||
//
|
||||
// FetchCert returns an error if the CA's response or chain was unreasonably large.
|
||||
// Callers are encouraged to parse the returned value to ensure the certificate is valid
|
||||
// and has expected features.
|
||||
func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) {
|
||||
for {
|
||||
res, err := ctxhttp.Get(ctx, c.HTTPClient, url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode == http.StatusOK {
|
||||
return responseCert(ctx, c.HTTPClient, res, bundle)
|
||||
}
|
||||
if res.StatusCode > 299 {
|
||||
return nil, responseError(res)
|
||||
}
|
||||
d := retryAfter(res.Header.Get("retry-after"), 3*time.Second)
|
||||
select {
|
||||
case <-time.After(d):
|
||||
// retry
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RevokeCert revokes a previously issued certificate cert, provided in DER format.
|
||||
//
|
||||
// The key argument, used to sign the request, must be authorized
|
||||
// to revoke the certificate. It's up to the CA to decide which keys are authorized.
|
||||
// For instance, the key pair of the certificate may be authorized.
|
||||
// If the key is nil, c.Key is used instead.
|
||||
func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error {
|
||||
if _, err := c.Discover(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
body := &struct {
|
||||
Resource string `json:"resource"`
|
||||
Cert string `json:"certificate"`
|
||||
Reason int `json:"reason"`
|
||||
}{
|
||||
Resource: "revoke-cert",
|
||||
Cert: base64.RawURLEncoding.EncodeToString(cert),
|
||||
Reason: int(reason),
|
||||
}
|
||||
if key == nil {
|
||||
key = c.Key
|
||||
}
|
||||
res, err := postJWS(ctx, c.HTTPClient, key, c.dir.RevokeURL, body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return responseError(res)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AcceptTOS always returns true to indicate the acceptance of a CA's Terms of Service
|
||||
// during account registration. See Register method of Client for more details.
|
||||
func AcceptTOS(tosURL string) bool { return true }
|
||||
|
||||
// Register creates a new account registration by following the "new-reg" flow.
|
||||
// It returns registered account. The a argument is not modified.
|
||||
//
|
||||
// The registration may require the caller to agree to the CA's Terms of Service (TOS).
|
||||
// If so, and the account has not indicated the acceptance of the terms (see Account for details),
|
||||
// Register 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 caller can use AcceptTOS.
|
||||
func (c *Client) Register(ctx context.Context, a *Account, prompt func(tosURL string) bool) (*Account, error) {
|
||||
if _, err := c.Discover(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var err error
|
||||
if a, err = c.doReg(ctx, c.dir.RegURL, "new-reg", a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var accept bool
|
||||
if a.CurrentTerms != "" && a.CurrentTerms != a.AgreedTerms {
|
||||
accept = prompt(a.CurrentTerms)
|
||||
}
|
||||
if accept {
|
||||
a.AgreedTerms = a.CurrentTerms
|
||||
a, err = c.UpdateReg(ctx, a)
|
||||
}
|
||||
return a, err
|
||||
}
|
||||
|
||||
// GetReg retrieves an existing registration.
|
||||
// The url argument is an Account URI.
|
||||
func (c *Client) GetReg(ctx context.Context, url string) (*Account, error) {
|
||||
a, err := c.doReg(ctx, url, "reg", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a.URI = url
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// UpdateReg updates an existing registration.
|
||||
// It returns an updated account copy. The provided account is not modified.
|
||||
func (c *Client) UpdateReg(ctx context.Context, a *Account) (*Account, error) {
|
||||
uri := a.URI
|
||||
a, err := c.doReg(ctx, uri, "reg", a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a.URI = uri
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// Authorize performs the initial step in an authorization flow.
|
||||
// The caller will then need to choose from and perform a set of returned
|
||||
// challenges using c.Accept in order to successfully complete authorization.
|
||||
//
|
||||
// If an authorization has been previously granted, the CA may return
|
||||
// a valid authorization (Authorization.Status is StatusValid). If so, the caller
|
||||
// need not fulfill any challenge and can proceed to requesting a certificate.
|
||||
func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error) {
|
||||
if _, err := c.Discover(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
type authzID struct {
|
||||
Type string `json:"type"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
req := struct {
|
||||
Resource string `json:"resource"`
|
||||
Identifier authzID `json:"identifier"`
|
||||
}{
|
||||
Resource: "new-authz",
|
||||
Identifier: authzID{Type: "dns", Value: domain},
|
||||
}
|
||||
res, err := postJWS(ctx, c.HTTPClient, c.Key, c.dir.AuthzURL, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusCreated {
|
||||
return nil, responseError(res)
|
||||
}
|
||||
|
||||
var v wireAuthz
|
||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||
return nil, fmt.Errorf("acme: invalid response: %v", err)
|
||||
}
|
||||
if v.Status != StatusPending && v.Status != StatusValid {
|
||||
return nil, fmt.Errorf("acme: unexpected status: %s", v.Status)
|
||||
}
|
||||
return v.authorization(res.Header.Get("Location")), nil
|
||||
}
|
||||
|
||||
// GetAuthorization retrieves an authorization identified by the given URL.
|
||||
//
|
||||
// If a caller needs to poll an authorization until its status is final,
|
||||
// see the WaitAuthorization method.
|
||||
func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) {
|
||||
res, err := ctxhttp.Get(ctx, c.HTTPClient, url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
|
||||
return nil, responseError(res)
|
||||
}
|
||||
var v wireAuthz
|
||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||
return nil, fmt.Errorf("acme: invalid response: %v", err)
|
||||
}
|
||||
return v.authorization(url), nil
|
||||
}
|
||||
|
||||
// RevokeAuthorization relinquishes an existing authorization identified
|
||||
// by the given URL.
|
||||
// The url argument is an Authorization.URI value.
|
||||
//
|
||||
// If successful, the caller will be required to obtain a new authorization
|
||||
// using the Authorize method before being able to request a new certificate
|
||||
// for the domain associated with the authorization.
|
||||
//
|
||||
// It does not revoke existing certificates.
|
||||
func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
|
||||
req := struct {
|
||||
Resource string `json:"resource"`
|
||||
Delete bool `json:"delete"`
|
||||
}{
|
||||
Resource: "authz",
|
||||
Delete: true,
|
||||
}
|
||||
res, err := postJWS(ctx, c.HTTPClient, c.Key, url, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return responseError(res)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WaitAuthorization polls an authorization at the given URL
|
||||
// until it is in one of the final states, StatusValid or StatusInvalid,
|
||||
// or the context is done.
|
||||
//
|
||||
// It returns a non-nil Authorization only if its Status is StatusValid.
|
||||
// In all other cases WaitAuthorization returns an error.
|
||||
// If the Status is StatusInvalid, the returned error is ErrAuthorizationFailed.
|
||||
func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) {
|
||||
var count int
|
||||
sleep := func(v string, inc int) error {
|
||||
count += inc
|
||||
d := backoff(count, 10*time.Second)
|
||||
d = retryAfter(v, d)
|
||||
wakeup := time.NewTimer(d)
|
||||
defer wakeup.Stop()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-wakeup.C:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
res, err := ctxhttp.Get(ctx, c.HTTPClient, url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
retry := res.Header.Get("retry-after")
|
||||
if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
|
||||
res.Body.Close()
|
||||
if err := sleep(retry, 1); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
var raw wireAuthz
|
||||
err = json.NewDecoder(res.Body).Decode(&raw)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
if err := sleep(retry, 0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
if raw.Status == StatusValid {
|
||||
return raw.authorization(url), nil
|
||||
}
|
||||
if raw.Status == StatusInvalid {
|
||||
return nil, ErrAuthorizationFailed
|
||||
}
|
||||
if err := sleep(retry, 0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetChallenge retrieves the current status of an challenge.
|
||||
//
|
||||
// A client typically polls a challenge status using this method.
|
||||
func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) {
|
||||
res, err := ctxhttp.Get(ctx, c.HTTPClient, url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
|
||||
return nil, responseError(res)
|
||||
}
|
||||
v := wireChallenge{URI: url}
|
||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||
return nil, fmt.Errorf("acme: invalid response: %v", err)
|
||||
}
|
||||
return v.challenge(), nil
|
||||
}
|
||||
|
||||
// Accept informs the server that the client accepts one of its challenges
|
||||
// previously obtained with c.Authorize.
|
||||
//
|
||||
// The server will then perform the validation asynchronously.
|
||||
func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error) {
|
||||
auth, err := keyAuth(c.Key.Public(), chal.Token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := struct {
|
||||
Resource string `json:"resource"`
|
||||
Type string `json:"type"`
|
||||
Auth string `json:"keyAuthorization"`
|
||||
}{
|
||||
Resource: "challenge",
|
||||
Type: chal.Type,
|
||||
Auth: auth,
|
||||
}
|
||||
res, err := postJWS(ctx, c.HTTPClient, c.Key, chal.URI, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
// Note: the protocol specifies 200 as the expected response code, but
|
||||
// letsencrypt seems to be returning 202.
|
||||
if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
|
||||
return nil, responseError(res)
|
||||
}
|
||||
|
||||
var v wireChallenge
|
||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||
return nil, fmt.Errorf("acme: invalid response: %v", err)
|
||||
}
|
||||
return v.challenge(), nil
|
||||
}
|
||||
|
||||
// DNS01ChallengeRecord returns a DNS record value for a dns-01 challenge response.
|
||||
// A TXT record containing the returned value must be provisioned under
|
||||
// "_acme-challenge" name of the domain being validated.
|
||||
//
|
||||
// The token argument is a Challenge.Token value.
|
||||
func (c *Client) DNS01ChallengeRecord(token string) (string, error) {
|
||||
ka, err := keyAuth(c.Key.Public(), token)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
b := sha256.Sum256([]byte(ka))
|
||||
return base64.RawURLEncoding.EncodeToString(b[:]), nil
|
||||
}
|
||||
|
||||
// HTTP01ChallengeResponse returns the response for an http-01 challenge.
|
||||
// Servers should respond with the value to HTTP requests at the URL path
|
||||
// provided by HTTP01ChallengePath to validate the challenge and prove control
|
||||
// over a domain name.
|
||||
//
|
||||
// The token argument is a Challenge.Token value.
|
||||
func (c *Client) HTTP01ChallengeResponse(token string) (string, error) {
|
||||
return keyAuth(c.Key.Public(), token)
|
||||
}
|
||||
|
||||
// HTTP01ChallengePath returns the URL path at which the response for an http-01 challenge
|
||||
// should be provided by the servers.
|
||||
// The response value can be obtained with HTTP01ChallengeResponse.
|
||||
//
|
||||
// The token argument is a Challenge.Token value.
|
||||
func (c *Client) HTTP01ChallengePath(token string) string {
|
||||
return "/.well-known/acme-challenge/" + token
|
||||
}
|
||||
|
||||
// TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response.
|
||||
// Servers can present the certificate to validate the challenge and prove control
|
||||
// over a domain name.
|
||||
//
|
||||
// The implementation is incomplete in that the returned value is a single certificate,
|
||||
// computed only for Z0 of the key authorization. ACME CAs are expected to update
|
||||
// their implementations to use the newer version, TLS-SNI-02.
|
||||
// For more details on TLS-SNI-01 see https://tools.ietf.org/html/draft-ietf-acme-acme-01#section-7.3.
|
||||
//
|
||||
// The token argument is a Challenge.Token value.
|
||||
// If a WithKey option is provided, its private part signs the returned cert,
|
||||
// and the public part is used to specify the signee.
|
||||
// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
|
||||
//
|
||||
// The returned certificate is valid for the next 24 hours and must be presented only when
|
||||
// the server name of the client hello matches exactly the returned name value.
|
||||
func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
|
||||
ka, err := keyAuth(c.Key.Public(), token)
|
||||
if err != nil {
|
||||
return tls.Certificate{}, "", err
|
||||
}
|
||||
b := sha256.Sum256([]byte(ka))
|
||||
h := hex.EncodeToString(b[:])
|
||||
name = fmt.Sprintf("%s.%s.acme.invalid", h[:32], h[32:])
|
||||
cert, err = tlsChallengeCert([]string{name}, opt)
|
||||
if err != nil {
|
||||
return tls.Certificate{}, "", err
|
||||
}
|
||||
return cert, name, nil
|
||||
}
|
||||
|
||||
// TLSSNI02ChallengeCert creates a certificate for TLS-SNI-02 challenge response.
|
||||
// Servers can present the certificate to validate the challenge and prove control
|
||||
// over a domain name. For more details on TLS-SNI-02 see
|
||||
// https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.3.
|
||||
//
|
||||
// The token argument is a Challenge.Token value.
|
||||
// If a WithKey option is provided, its private part signs the returned cert,
|
||||
// and the public part is used to specify the signee.
|
||||
// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
|
||||
//
|
||||
// The returned certificate is valid for the next 24 hours and must be presented only when
|
||||
// the server name in the client hello matches exactly the returned name value.
|
||||
func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
|
||||
b := sha256.Sum256([]byte(token))
|
||||
h := hex.EncodeToString(b[:])
|
||||
sanA := fmt.Sprintf("%s.%s.token.acme.invalid", h[:32], h[32:])
|
||||
|
||||
ka, err := keyAuth(c.Key.Public(), token)
|
||||
if err != nil {
|
||||
return tls.Certificate{}, "", err
|
||||
}
|
||||
b = sha256.Sum256([]byte(ka))
|
||||
h = hex.EncodeToString(b[:])
|
||||
sanB := fmt.Sprintf("%s.%s.ka.acme.invalid", h[:32], h[32:])
|
||||
|
||||
cert, err = tlsChallengeCert([]string{sanA, sanB}, opt)
|
||||
if err != nil {
|
||||
return tls.Certificate{}, "", err
|
||||
}
|
||||
return cert, sanA, nil
|
||||
}
|
||||
|
||||
// doReg sends all types of registration requests.
|
||||
// The type of request is identified by typ argument, which is a "resource"
|
||||
// in the ACME spec terms.
|
||||
//
|
||||
// A non-nil acct argument indicates whether the intention is to mutate data
|
||||
// of the Account. Only Contact and Agreement of its fields are used
|
||||
// in such cases.
|
||||
func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Account) (*Account, error) {
|
||||
req := struct {
|
||||
Resource string `json:"resource"`
|
||||
Contact []string `json:"contact,omitempty"`
|
||||
Agreement string `json:"agreement,omitempty"`
|
||||
}{
|
||||
Resource: typ,
|
||||
}
|
||||
if acct != nil {
|
||||
req.Contact = acct.Contact
|
||||
req.Agreement = acct.AgreedTerms
|
||||
}
|
||||
res, err := postJWS(ctx, c.HTTPClient, c.Key, url, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode < 200 || res.StatusCode > 299 {
|
||||
return nil, responseError(res)
|
||||
}
|
||||
|
||||
var v struct {
|
||||
Contact []string
|
||||
Agreement string
|
||||
Authorizations string
|
||||
Certificates string
|
||||
}
|
||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||
return nil, fmt.Errorf("acme: invalid response: %v", err)
|
||||
}
|
||||
var tos string
|
||||
if v := linkHeader(res.Header, "terms-of-service"); len(v) > 0 {
|
||||
tos = v[0]
|
||||
}
|
||||
var authz string
|
||||
if v := linkHeader(res.Header, "next"); len(v) > 0 {
|
||||
authz = v[0]
|
||||
}
|
||||
return &Account{
|
||||
URI: res.Header.Get("Location"),
|
||||
Contact: v.Contact,
|
||||
AgreedTerms: v.Agreement,
|
||||
CurrentTerms: tos,
|
||||
Authz: authz,
|
||||
Authorizations: v.Authorizations,
|
||||
Certificates: v.Certificates,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func responseCert(ctx context.Context, client *http.Client, res *http.Response, bundle bool) ([][]byte, error) {
|
||||
b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("acme: response stream: %v", err)
|
||||
}
|
||||
if len(b) > maxCertSize {
|
||||
return nil, errors.New("acme: certificate is too big")
|
||||
}
|
||||
cert := [][]byte{b}
|
||||
if !bundle {
|
||||
return cert, nil
|
||||
}
|
||||
|
||||
// Append CA chain cert(s).
|
||||
// At least one is required according to the spec:
|
||||
// https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-6.3.1
|
||||
up := linkHeader(res.Header, "up")
|
||||
if len(up) == 0 {
|
||||
return nil, errors.New("acme: rel=up link not found")
|
||||
}
|
||||
if len(up) > maxChainLen {
|
||||
return nil, errors.New("acme: rel=up link is too large")
|
||||
}
|
||||
for _, url := range up {
|
||||
cc, err := chainCert(ctx, client, url, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cert = append(cert, cc...)
|
||||
}
|
||||
return cert, nil
|
||||
}
|
||||
|
||||
// responseError creates an error of Error type from resp.
|
||||
func responseError(resp *http.Response) error {
|
||||
// don't care if ReadAll returns an error:
|
||||
// json.Unmarshal will fail in that case anyway
|
||||
b, _ := ioutil.ReadAll(resp.Body)
|
||||
e := struct {
|
||||
Status int
|
||||
Type string
|
||||
Detail string
|
||||
}{
|
||||
Status: resp.StatusCode,
|
||||
}
|
||||
if err := json.Unmarshal(b, &e); err != nil {
|
||||
// this is not a regular error response:
|
||||
// populate detail with anything we received,
|
||||
// e.Status will already contain HTTP response code value
|
||||
e.Detail = string(b)
|
||||
if e.Detail == "" {
|
||||
e.Detail = resp.Status
|
||||
}
|
||||
}
|
||||
return &Error{
|
||||
StatusCode: e.Status,
|
||||
ProblemType: e.Type,
|
||||
Detail: e.Detail,
|
||||
Header: resp.Header,
|
||||
}
|
||||
}
|
||||
|
||||
// chainCert fetches CA certificate chain recursively by following "up" links.
|
||||
// Each recursive call increments the depth by 1, resulting in an error
|
||||
// if the recursion level reaches maxChainLen.
|
||||
//
|
||||
// First chainCert call starts with depth of 0.
|
||||
func chainCert(ctx context.Context, client *http.Client, url string, depth int) ([][]byte, error) {
|
||||
if depth >= maxChainLen {
|
||||
return nil, errors.New("acme: certificate chain is too deep")
|
||||
}
|
||||
|
||||
res, err := ctxhttp.Get(ctx, client, url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, responseError(res)
|
||||
}
|
||||
b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(b) > maxCertSize {
|
||||
return nil, errors.New("acme: certificate is too big")
|
||||
}
|
||||
chain := [][]byte{b}
|
||||
|
||||
uplink := linkHeader(res.Header, "up")
|
||||
if len(uplink) > maxChainLen {
|
||||
return nil, errors.New("acme: certificate chain is too large")
|
||||
}
|
||||
for _, up := range uplink {
|
||||
cc, err := chainCert(ctx, client, up, depth+1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chain = append(chain, cc...)
|
||||
}
|
||||
|
||||
return chain, nil
|
||||
}
|
||||
|
||||
// postJWS signs the body with the given key and POSTs it to the provided url.
|
||||
// The body argument must be JSON-serializable.
|
||||
func postJWS(ctx context.Context, client *http.Client, key crypto.Signer, url string, body interface{}) (*http.Response, error) {
|
||||
nonce, err := fetchNonce(ctx, client, url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b, err := jwsEncodeJSON(body, key, nonce)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ctxhttp.Post(ctx, client, url, "application/jose+json", bytes.NewReader(b))
|
||||
}
|
||||
|
||||
func fetchNonce(ctx context.Context, client *http.Client, url string) (string, error) {
|
||||
resp, err := ctxhttp.Head(ctx, client, url)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
enc := resp.Header.Get("replay-nonce")
|
||||
if enc == "" {
|
||||
return "", errors.New("acme: nonce not found")
|
||||
}
|
||||
return enc, nil
|
||||
}
|
||||
|
||||
// linkHeader returns URI-Reference values of all Link headers
|
||||
// with relation-type rel.
|
||||
// See https://tools.ietf.org/html/rfc5988#section-5 for details.
|
||||
func linkHeader(h http.Header, rel string) []string {
|
||||
var links []string
|
||||
for _, v := range h["Link"] {
|
||||
parts := strings.Split(v, ";")
|
||||
for _, p := range parts {
|
||||
p = strings.TrimSpace(p)
|
||||
if !strings.HasPrefix(p, "rel=") {
|
||||
continue
|
||||
}
|
||||
if v := strings.Trim(p[4:], `"`); v == rel {
|
||||
links = append(links, strings.Trim(parts[0], "<>"))
|
||||
}
|
||||
}
|
||||
}
|
||||
return links
|
||||
}
|
||||
|
||||
// retryAfter parses a Retry-After HTTP header value,
|
||||
// trying to convert v into an int (seconds) or use http.ParseTime otherwise.
|
||||
// It returns d if v cannot be parsed.
|
||||
func retryAfter(v string, d time.Duration) time.Duration {
|
||||
if i, err := strconv.Atoi(v); err == nil {
|
||||
return time.Duration(i) * time.Second
|
||||
}
|
||||
t, err := http.ParseTime(v)
|
||||
if err != nil {
|
||||
return d
|
||||
}
|
||||
return t.Sub(timeNow())
|
||||
}
|
||||
|
||||
// backoff computes a duration after which an n+1 retry iteration should occur
|
||||
// using truncated exponential backoff algorithm.
|
||||
//
|
||||
// The n argument is always bounded between 0 and 30.
|
||||
// The max argument defines upper bound for the returned value.
|
||||
func backoff(n int, max time.Duration) time.Duration {
|
||||
if n < 0 {
|
||||
n = 0
|
||||
}
|
||||
if n > 30 {
|
||||
n = 30
|
||||
}
|
||||
var d time.Duration
|
||||
if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil {
|
||||
d = time.Duration(x.Int64()) * time.Millisecond
|
||||
}
|
||||
d += time.Duration(1<<uint(n)) * time.Second
|
||||
if d > max {
|
||||
return max
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// keyAuth generates a key authorization string for a given token.
|
||||
func keyAuth(pub crypto.PublicKey, token string) (string, error) {
|
||||
th, err := JWKThumbprint(pub)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("%s.%s", token, th), nil
|
||||
}
|
||||
|
||||
// tlsChallengeCert creates a temporary certificate for TLS-SNI challenges
|
||||
// with the given SANs and auto-generated public/private key pair.
|
||||
// To create a cert with a custom key pair, specify WithKey option.
|
||||
func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
|
||||
var (
|
||||
key crypto.Signer
|
||||
tmpl *x509.Certificate
|
||||
)
|
||||
for _, o := range opt {
|
||||
switch o := o.(type) {
|
||||
case *certOptKey:
|
||||
if key != nil {
|
||||
return tls.Certificate{}, errors.New("acme: duplicate key option")
|
||||
}
|
||||
key = o.key
|
||||
case *certOptTemplate:
|
||||
var t = *(*x509.Certificate)(o) // shallow copy is ok
|
||||
tmpl = &t
|
||||
default:
|
||||
// package's fault, if we let this happen:
|
||||
panic(fmt.Sprintf("unsupported option type %T", o))
|
||||
}
|
||||
}
|
||||
if key == nil {
|
||||
var err error
|
||||
if key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader); err != nil {
|
||||
return tls.Certificate{}, err
|
||||
}
|
||||
}
|
||||
if tmpl == nil {
|
||||
tmpl = &x509.Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().Add(24 * time.Hour),
|
||||
BasicConstraintsValid: true,
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment,
|
||||
}
|
||||
}
|
||||
tmpl.DNSNames = san
|
||||
|
||||
der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, key.Public(), key)
|
||||
if err != nil {
|
||||
return tls.Certificate{}, err
|
||||
}
|
||||
return tls.Certificate{
|
||||
Certificate: [][]byte{der},
|
||||
PrivateKey: key,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// encodePEM returns b encoded as PEM with block of type typ.
|
||||
func encodePEM(typ string, b []byte) []byte {
|
||||
pb := &pem.Block{Type: typ, Bytes: b}
|
||||
return pem.EncodeToMemory(pb)
|
||||
}
|
||||
|
||||
// timeNow is useful for testing for fixed current time.
|
||||
var timeNow = time.Now
|
||||
538
vendor/golang.org/x/crypto/acme/internal/acme/acme_test.go → vendor/golang.org/x/crypto/acme/acme_test.go
сгенерированный
поставляемый
538
vendor/golang.org/x/crypto/acme/internal/acme/acme_test.go → vendor/golang.org/x/crypto/acme/acme_test.go
сгенерированный
поставляемый
@@ -5,7 +5,10 @@
|
||||
package acme
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/base64"
|
||||
@@ -16,6 +19,7 @@ import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -58,21 +62,22 @@ func TestDiscover(t *testing.T) {
|
||||
}`, reg, authz, cert, revoke)
|
||||
}))
|
||||
defer ts.Close()
|
||||
ep, err := (&Client{}).Discover(ts.URL)
|
||||
c := Client{DirectoryURL: ts.URL}
|
||||
dir, err := c.Discover(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if ep.RegURL != reg {
|
||||
t.Errorf("RegURL = %q; want %q", ep.RegURL, reg)
|
||||
if dir.RegURL != reg {
|
||||
t.Errorf("dir.RegURL = %q; want %q", dir.RegURL, reg)
|
||||
}
|
||||
if ep.AuthzURL != authz {
|
||||
t.Errorf("authzURL = %q; want %q", ep.AuthzURL, authz)
|
||||
if dir.AuthzURL != authz {
|
||||
t.Errorf("dir.AuthzURL = %q; want %q", dir.AuthzURL, authz)
|
||||
}
|
||||
if ep.CertURL != cert {
|
||||
t.Errorf("certURL = %q; want %q", ep.CertURL, cert)
|
||||
if dir.CertURL != cert {
|
||||
t.Errorf("dir.CertURL = %q; want %q", dir.CertURL, cert)
|
||||
}
|
||||
if ep.RevokeURL != revoke {
|
||||
t.Errorf("revokeURL = %q; want %q", ep.RevokeURL, revoke)
|
||||
if dir.RevokeURL != revoke {
|
||||
t.Errorf("dir.RevokeURL = %q; want %q", dir.RevokeURL, revoke)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,17 +114,22 @@ func TestRegister(t *testing.T) {
|
||||
w.Header().Add("Link", `<https://ca.tld/acme/terms>;rel="terms-of-service"`)
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
b, _ := json.Marshal(contacts)
|
||||
fmt.Fprintf(w, `{
|
||||
"key":%q,
|
||||
"contact":%s
|
||||
}`, testKeyThumbprint, b)
|
||||
fmt.Fprintf(w, `{"contact": %s}`, b)
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
c := Client{Key: testKey}
|
||||
prompt := func(url string) bool {
|
||||
const terms = "https://ca.tld/acme/terms"
|
||||
if url != terms {
|
||||
t.Errorf("prompt url = %q; want %q", url, terms)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
c := Client{Key: testKeyEC, dir: &Directory{RegURL: ts.URL}}
|
||||
a := &Account{Contact: contacts}
|
||||
var err error
|
||||
if a, err = c.Register(ts.URL, a); err != nil {
|
||||
if a, err = c.Register(context.Background(), a, prompt); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if a.URI != "https://ca.tld/acme/reg/1" {
|
||||
@@ -172,18 +182,14 @@ func TestUpdateReg(t *testing.T) {
|
||||
w.Header().Add("Link", fmt.Sprintf(`<%s>;rel="terms-of-service"`, terms))
|
||||
w.WriteHeader(http.StatusOK)
|
||||
b, _ := json.Marshal(contacts)
|
||||
fmt.Fprintf(w, `{
|
||||
"key":%q,
|
||||
"contact":%s,
|
||||
"agreement":%q
|
||||
}`, testKeyThumbprint, b, terms)
|
||||
fmt.Fprintf(w, `{"contact":%s, "agreement":%q}`, b, terms)
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
c := Client{Key: testKey}
|
||||
a := &Account{Contact: contacts, AgreedTerms: terms}
|
||||
c := Client{Key: testKeyEC}
|
||||
a := &Account{URI: ts.URL, Contact: contacts, AgreedTerms: terms}
|
||||
var err error
|
||||
if a, err = c.UpdateReg(ts.URL, a); err != nil {
|
||||
if a, err = c.UpdateReg(context.Background(), a); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if a.Authz != "https://ca.tld/acme/new-authz" {
|
||||
@@ -195,6 +201,9 @@ func TestUpdateReg(t *testing.T) {
|
||||
if a.CurrentTerms != terms {
|
||||
t.Errorf("a.CurrentTerms = %q; want %q", a.CurrentTerms, terms)
|
||||
}
|
||||
if a.URI != ts.URL {
|
||||
t.Errorf("a.URI = %q; want %q", a.URI, ts.URL)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetReg(t *testing.T) {
|
||||
@@ -234,16 +243,12 @@ func TestGetReg(t *testing.T) {
|
||||
w.Header().Add("Link", fmt.Sprintf(`<%s>;rel="terms-of-service"`, newTerms))
|
||||
w.WriteHeader(http.StatusOK)
|
||||
b, _ := json.Marshal(contacts)
|
||||
fmt.Fprintf(w, `{
|
||||
"key":%q,
|
||||
"contact":%s,
|
||||
"agreement":%q
|
||||
}`, testKeyThumbprint, b, terms)
|
||||
fmt.Fprintf(w, `{"contact":%s, "agreement":%q}`, b, terms)
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
c := Client{Key: testKey}
|
||||
a, err := c.GetReg(ts.URL)
|
||||
c := Client{Key: testKeyEC}
|
||||
a, err := c.GetReg(context.Background(), ts.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -256,6 +261,9 @@ func TestGetReg(t *testing.T) {
|
||||
if a.CurrentTerms != newTerms {
|
||||
t.Errorf("a.CurrentTerms = %q; want %q", a.CurrentTerms, newTerms)
|
||||
}
|
||||
if a.URI != ts.URL {
|
||||
t.Errorf("a.URI = %q; want %q", a.URI, ts.URL)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthorize(t *testing.T) {
|
||||
@@ -311,8 +319,8 @@ func TestAuthorize(t *testing.T) {
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
cl := Client{Key: testKey}
|
||||
auth, err := cl.Authorize(ts.URL, "example.com")
|
||||
cl := Client{Key: testKeyEC, dir: &Directory{AuthzURL: ts.URL}}
|
||||
auth, err := cl.Authorize(context.Background(), "example.com")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -362,7 +370,24 @@ func TestAuthorize(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPollAuthz(t *testing.T) {
|
||||
func TestAuthorizeValid(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "HEAD" {
|
||||
w.Header().Set("replay-nonce", "nonce")
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
w.Write([]byte(`{"status":"valid"}`))
|
||||
}))
|
||||
defer ts.Close()
|
||||
client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}}
|
||||
_, err := client.Authorize(context.Background(), "example.com")
|
||||
if err != nil {
|
||||
t.Errorf("err = %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAuthorization(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "GET" {
|
||||
t.Errorf("r.Method = %q; want GET", r.Method)
|
||||
@@ -390,8 +415,8 @@ func TestPollAuthz(t *testing.T) {
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
cl := Client{Key: testKey}
|
||||
auth, err := cl.GetAuthz(ts.URL)
|
||||
cl := Client{Key: testKeyEC}
|
||||
auth, err := cl.GetAuthorization(context.Background(), ts.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -438,6 +463,129 @@ func TestPollAuthz(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWaitAuthorization(t *testing.T) {
|
||||
var count int
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
count++
|
||||
w.Header().Set("retry-after", "0")
|
||||
if count > 1 {
|
||||
fmt.Fprintf(w, `{"status":"valid"}`)
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, `{"status":"pending"}`)
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
type res struct {
|
||||
authz *Authorization
|
||||
err error
|
||||
}
|
||||
done := make(chan res)
|
||||
defer close(done)
|
||||
go func() {
|
||||
var client Client
|
||||
a, err := client.WaitAuthorization(context.Background(), ts.URL)
|
||||
done <- res{a, err}
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatal("WaitAuthz took too long to return")
|
||||
case res := <-done:
|
||||
if res.err != nil {
|
||||
t.Fatalf("res.err = %v", res.err)
|
||||
}
|
||||
if res.authz == nil {
|
||||
t.Fatal("res.authz is nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWaitAuthorizationInvalid(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, `{"status":"invalid"}`)
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
res := make(chan error)
|
||||
defer close(res)
|
||||
go func() {
|
||||
var client Client
|
||||
_, err := client.WaitAuthorization(context.Background(), ts.URL)
|
||||
res <- err
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-time.After(3 * time.Second):
|
||||
t.Fatal("WaitAuthz took too long to return")
|
||||
case err := <-res:
|
||||
if err == nil {
|
||||
t.Error("err is nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWaitAuthorizationCancel(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("retry-after", "60")
|
||||
fmt.Fprintf(w, `{"status":"pending"}`)
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
res := make(chan error)
|
||||
defer close(res)
|
||||
go func() {
|
||||
var client Client
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
|
||||
defer cancel()
|
||||
_, err := client.WaitAuthorization(ctx, ts.URL)
|
||||
res <- err
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("WaitAuthz took too long to return")
|
||||
case err := <-res:
|
||||
if err == nil {
|
||||
t.Error("err is nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRevokeAuthorization(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "HEAD" {
|
||||
w.Header().Set("replay-nonce", "nonce")
|
||||
return
|
||||
}
|
||||
switch r.URL.Path {
|
||||
case "/1":
|
||||
var req struct {
|
||||
Resource string
|
||||
Delete bool
|
||||
}
|
||||
decodeJWSRequest(t, &req, r)
|
||||
if req.Resource != "authz" {
|
||||
t.Errorf("req.Resource = %q; want authz", req.Resource)
|
||||
}
|
||||
if !req.Delete {
|
||||
t.Errorf("req.Delete is false")
|
||||
}
|
||||
case "/2":
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}))
|
||||
defer ts.Close()
|
||||
client := &Client{Key: testKey}
|
||||
ctx := context.Background()
|
||||
if err := client.RevokeAuthorization(ctx, ts.URL+"/1"); err != nil {
|
||||
t.Errorf("err = %v", err)
|
||||
}
|
||||
if client.RevokeAuthorization(ctx, ts.URL+"/2") == nil {
|
||||
t.Error("nil error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPollChallenge(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "GET" {
|
||||
@@ -453,8 +601,8 @@ func TestPollChallenge(t *testing.T) {
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
cl := Client{Key: testKey}
|
||||
chall, err := cl.GetChallenge(ts.URL)
|
||||
cl := Client{Key: testKeyEC}
|
||||
chall, err := cl.GetChallenge(context.Background(), ts.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -497,7 +645,7 @@ func TestAcceptChallenge(t *testing.T) {
|
||||
if j.Type != "http-01" {
|
||||
t.Errorf(`type = %q; want "http-01"`, j.Type)
|
||||
}
|
||||
keyAuth := "token1." + testKeyThumbprint
|
||||
keyAuth := "token1." + testKeyECThumbprint
|
||||
if j.Auth != keyAuth {
|
||||
t.Errorf(`keyAuthorization = %q; want %q`, j.Auth, keyAuth)
|
||||
}
|
||||
@@ -514,8 +662,8 @@ func TestAcceptChallenge(t *testing.T) {
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
cl := Client{Key: testKey}
|
||||
c, err := cl.Accept(&Challenge{
|
||||
cl := Client{Key: testKeyEC}
|
||||
c, err := cl.Accept(context.Background(), &Challenge{
|
||||
URI: ts.URL,
|
||||
Token: "token1",
|
||||
Type: "http-01",
|
||||
@@ -582,7 +730,7 @@ func TestNewCert(t *testing.T) {
|
||||
BasicConstraintsValid: true,
|
||||
}
|
||||
|
||||
sampleCert, err := x509.CreateCertificate(rand.Reader, &template, &template, &testKey.PublicKey, testKey)
|
||||
sampleCert, err := x509.CreateCertificate(rand.Reader, &template, &template, &testKeyEC.PublicKey, testKeyEC)
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating certificate: %v", err)
|
||||
}
|
||||
@@ -600,13 +748,13 @@ func TestNewCert(t *testing.T) {
|
||||
Organization: []string{"goacme"},
|
||||
},
|
||||
}
|
||||
csrb, err := x509.CreateCertificateRequest(rand.Reader, &csr, testKey)
|
||||
csrb, err := x509.CreateCertificateRequest(rand.Reader, &csr, testKeyEC)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
c := Client{Key: testKey}
|
||||
cert, certURL, err := c.CreateCert(context.Background(), ts.URL, csrb, notAfter.Sub(notBefore), false)
|
||||
c := Client{Key: testKeyEC, dir: &Directory{CertURL: ts.URL}}
|
||||
cert, certURL, err := c.CreateCert(context.Background(), csrb, notAfter.Sub(notBefore), false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -619,15 +767,22 @@ func TestNewCert(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFetchCert(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte{1})
|
||||
var count byte
|
||||
var ts *httptest.Server
|
||||
ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
count++
|
||||
if count < 3 {
|
||||
up := fmt.Sprintf("<%s>;rel=up", ts.URL)
|
||||
w.Header().Set("link", up)
|
||||
}
|
||||
w.Write([]byte{count})
|
||||
}))
|
||||
defer ts.Close()
|
||||
res, err := (&Client{}).FetchCert(context.Background(), ts.URL, false)
|
||||
res, err := (&Client{}).FetchCert(context.Background(), ts.URL, true)
|
||||
if err != nil {
|
||||
t.Fatalf("FetchCert: %v", err)
|
||||
}
|
||||
cert := [][]byte{{1}}
|
||||
cert := [][]byte{{1}, {2}, {3}}
|
||||
if !reflect.DeepEqual(res, cert) {
|
||||
t.Errorf("res = %v; want %v", res, cert)
|
||||
}
|
||||
@@ -675,6 +830,88 @@ func TestFetchCertCancel(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFetchCertDepth(t *testing.T) {
|
||||
var count byte
|
||||
var ts *httptest.Server
|
||||
ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
count++
|
||||
if count > maxChainLen+1 {
|
||||
t.Errorf("count = %d; want at most %d", count, maxChainLen+1)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
w.Header().Set("link", fmt.Sprintf("<%s>;rel=up", ts.URL))
|
||||
w.Write([]byte{count})
|
||||
}))
|
||||
defer ts.Close()
|
||||
_, err := (&Client{}).FetchCert(context.Background(), ts.URL, true)
|
||||
if err == nil {
|
||||
t.Errorf("err is nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFetchCertBreadth(t *testing.T) {
|
||||
var ts *httptest.Server
|
||||
ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
for i := 0; i < maxChainLen+1; i++ {
|
||||
w.Header().Add("link", fmt.Sprintf("<%s>;rel=up", ts.URL))
|
||||
}
|
||||
w.Write([]byte{1})
|
||||
}))
|
||||
defer ts.Close()
|
||||
_, err := (&Client{}).FetchCert(context.Background(), ts.URL, true)
|
||||
if err == nil {
|
||||
t.Errorf("err is nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFetchCertSize(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
b := bytes.Repeat([]byte{1}, maxCertSize+1)
|
||||
w.Write(b)
|
||||
}))
|
||||
defer ts.Close()
|
||||
_, err := (&Client{}).FetchCert(context.Background(), ts.URL, false)
|
||||
if err == nil {
|
||||
t.Errorf("err is nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRevokeCert(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "HEAD" {
|
||||
w.Header().Set("replay-nonce", "nonce")
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Resource string
|
||||
Certificate string
|
||||
Reason int
|
||||
}
|
||||
decodeJWSRequest(t, &req, r)
|
||||
if req.Resource != "revoke-cert" {
|
||||
t.Errorf("req.Resource = %q; want revoke-cert", req.Resource)
|
||||
}
|
||||
if req.Reason != 1 {
|
||||
t.Errorf("req.Reason = %d; want 1", req.Reason)
|
||||
}
|
||||
// echo -n cert | base64 | tr -d '=' | tr '/+' '_-'
|
||||
cert := "Y2VydA"
|
||||
if req.Certificate != cert {
|
||||
t.Errorf("req.Certificate = %q; want %q", req.Certificate, cert)
|
||||
}
|
||||
}))
|
||||
defer ts.Close()
|
||||
client := &Client{
|
||||
Key: testKeyEC,
|
||||
dir: &Directory{RevokeURL: ts.URL},
|
||||
}
|
||||
ctx := context.Background()
|
||||
if err := client.RevokeCert(ctx, nil, []byte("cert"), CRLReasonKeyCompromise); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFetchNonce(t *testing.T) {
|
||||
tests := []struct {
|
||||
code int
|
||||
@@ -695,7 +932,7 @@ func TestFetchNonce(t *testing.T) {
|
||||
defer ts.Close()
|
||||
for ; i < len(tests); i++ {
|
||||
test := tests[i]
|
||||
n, err := fetchNonce(http.DefaultClient, ts.URL)
|
||||
n, err := fetchNonce(context.Background(), http.DefaultClient, ts.URL)
|
||||
if n != test.nonce {
|
||||
t.Errorf("%d: n=%q; want %q", i, n, test.nonce)
|
||||
}
|
||||
@@ -713,16 +950,20 @@ func TestLinkHeader(t *testing.T) {
|
||||
`<https://example.com/acme/new-authz>;rel="next"`,
|
||||
`<https://example.com/acme/recover-reg>; rel=recover`,
|
||||
`<https://example.com/acme/terms>; foo=bar; rel="terms-of-service"`,
|
||||
`<dup>;rel="next"`,
|
||||
}}
|
||||
tests := []struct{ in, out string }{
|
||||
{"next", "https://example.com/acme/new-authz"},
|
||||
{"recover", "https://example.com/acme/recover-reg"},
|
||||
{"terms-of-service", "https://example.com/acme/terms"},
|
||||
{"empty", ""},
|
||||
tests := []struct {
|
||||
rel string
|
||||
out []string
|
||||
}{
|
||||
{"next", []string{"https://example.com/acme/new-authz", "dup"}},
|
||||
{"recover", []string{"https://example.com/acme/recover-reg"}},
|
||||
{"terms-of-service", []string{"https://example.com/acme/terms"}},
|
||||
{"empty", nil},
|
||||
}
|
||||
for i, test := range tests {
|
||||
if v := linkHeader(h, test.in); v != test.out {
|
||||
t.Errorf("%d: parseLinkHeader(%q): %q; want %q", i, test.in, v, test.out)
|
||||
if v := linkHeader(h, test.rel); !reflect.DeepEqual(v, test.out) {
|
||||
t.Errorf("%d: linkHeader(%q): %v; want %v", i, test.rel, v, test.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -757,3 +998,188 @@ func TestErrorResponse(t *testing.T) {
|
||||
t.Errorf("v.Header = %+v; want %+v", v.Header, res.Header)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSSNI01ChallengeCert(t *testing.T) {
|
||||
const (
|
||||
token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA"
|
||||
// echo -n <token.testKeyECThumbprint> | shasum -a 256
|
||||
san = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.acme.invalid"
|
||||
)
|
||||
|
||||
client := &Client{Key: testKeyEC}
|
||||
tlscert, name, err := client.TLSSNI01ChallengeCert(token)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if n := len(tlscert.Certificate); n != 1 {
|
||||
t.Fatalf("len(tlscert.Certificate) = %d; want 1", n)
|
||||
}
|
||||
cert, err := x509.ParseCertificate(tlscert.Certificate[0])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(cert.DNSNames) != 1 || cert.DNSNames[0] != san {
|
||||
t.Fatalf("cert.DNSNames = %v; want %q", cert.DNSNames, san)
|
||||
}
|
||||
if cert.DNSNames[0] != name {
|
||||
t.Errorf("cert.DNSNames[0] != name: %q vs %q", cert.DNSNames[0], name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSSNI02ChallengeCert(t *testing.T) {
|
||||
const (
|
||||
token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA"
|
||||
// echo -n evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA | shasum -a 256
|
||||
sanA = "7ea0aaa69214e71e02cebb18bb867736.09b730209baabf60e43d4999979ff139.token.acme.invalid"
|
||||
// echo -n <token.testKeyECThumbprint> | shasum -a 256
|
||||
sanB = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.ka.acme.invalid"
|
||||
)
|
||||
|
||||
client := &Client{Key: testKeyEC}
|
||||
tlscert, name, err := client.TLSSNI02ChallengeCert(token)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if n := len(tlscert.Certificate); n != 1 {
|
||||
t.Fatalf("len(tlscert.Certificate) = %d; want 1", n)
|
||||
}
|
||||
cert, err := x509.ParseCertificate(tlscert.Certificate[0])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
names := []string{sanA, sanB}
|
||||
if !reflect.DeepEqual(cert.DNSNames, names) {
|
||||
t.Fatalf("cert.DNSNames = %v;\nwant %v", cert.DNSNames, names)
|
||||
}
|
||||
sort.Strings(cert.DNSNames)
|
||||
i := sort.SearchStrings(cert.DNSNames, name)
|
||||
if i >= len(cert.DNSNames) || cert.DNSNames[i] != name {
|
||||
t.Errorf("%v doesn't have %q", cert.DNSNames, name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSChallengeCertOpt(t *testing.T) {
|
||||
key, err := rsa.GenerateKey(rand.Reader, 512)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tmpl := &x509.Certificate{
|
||||
SerialNumber: big.NewInt(2),
|
||||
Subject: pkix.Name{Organization: []string{"Test"}},
|
||||
DNSNames: []string{"should-be-overwritten"},
|
||||
}
|
||||
opts := []CertOption{WithKey(key), WithTemplate(tmpl)}
|
||||
|
||||
client := &Client{Key: testKeyEC}
|
||||
cert1, _, err := client.TLSSNI01ChallengeCert("token", opts...)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cert2, _, err := client.TLSSNI02ChallengeCert("token", opts...)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i, tlscert := range []tls.Certificate{cert1, cert2} {
|
||||
// verify generated cert private key
|
||||
tlskey, ok := tlscert.PrivateKey.(*rsa.PrivateKey)
|
||||
if !ok {
|
||||
t.Errorf("%d: tlscert.PrivateKey is %T; want *rsa.PrivateKey", i, tlscert.PrivateKey)
|
||||
continue
|
||||
}
|
||||
if tlskey.D.Cmp(key.D) != 0 {
|
||||
t.Errorf("%d: tlskey.D = %v; want %v", i, tlskey.D, key.D)
|
||||
}
|
||||
// verify generated cert public key
|
||||
x509Cert, err := x509.ParseCertificate(tlscert.Certificate[0])
|
||||
if err != nil {
|
||||
t.Errorf("%d: %v", i, err)
|
||||
continue
|
||||
}
|
||||
tlspub, ok := x509Cert.PublicKey.(*rsa.PublicKey)
|
||||
if !ok {
|
||||
t.Errorf("%d: x509Cert.PublicKey is %T; want *rsa.PublicKey", i, x509Cert.PublicKey)
|
||||
continue
|
||||
}
|
||||
if tlspub.N.Cmp(key.N) != 0 {
|
||||
t.Errorf("%d: tlspub.N = %v; want %v", i, tlspub.N, key.N)
|
||||
}
|
||||
// verify template option
|
||||
sn := big.NewInt(2)
|
||||
if x509Cert.SerialNumber.Cmp(sn) != 0 {
|
||||
t.Errorf("%d: SerialNumber = %v; want %v", i, x509Cert.SerialNumber, sn)
|
||||
}
|
||||
org := []string{"Test"}
|
||||
if !reflect.DeepEqual(x509Cert.Subject.Organization, org) {
|
||||
t.Errorf("%d: Subject.Organization = %+v; want %+v", i, x509Cert.Subject.Organization, org)
|
||||
}
|
||||
for _, v := range x509Cert.DNSNames {
|
||||
if !strings.HasSuffix(v, ".acme.invalid") {
|
||||
t.Errorf("%d: invalid DNSNames element: %q", i, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTP01Challenge(t *testing.T) {
|
||||
const (
|
||||
token = "xxx"
|
||||
// thumbprint is precomputed for testKeyEC in jws_test.go
|
||||
value = token + "." + testKeyECThumbprint
|
||||
urlpath = "/.well-known/acme-challenge/" + token
|
||||
)
|
||||
client := &Client{Key: testKeyEC}
|
||||
val, err := client.HTTP01ChallengeResponse(token)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if val != value {
|
||||
t.Errorf("val = %q; want %q", val, value)
|
||||
}
|
||||
if path := client.HTTP01ChallengePath(token); path != urlpath {
|
||||
t.Errorf("path = %q; want %q", path, urlpath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDNS01ChallengeRecord(t *testing.T) {
|
||||
// echo -n xxx.<testKeyECThumbprint> | \
|
||||
// openssl dgst -binary -sha256 | \
|
||||
// base64 | tr -d '=' | tr '/+' '_-'
|
||||
const value = "8DERMexQ5VcdJ_prpPiA0mVdp7imgbCgjsG4SqqNMIo"
|
||||
|
||||
client := &Client{Key: testKeyEC}
|
||||
val, err := client.DNS01ChallengeRecord("xxx")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if val != value {
|
||||
t.Errorf("val = %q; want %q", val, value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackoff(t *testing.T) {
|
||||
tt := []struct{ min, max time.Duration }{
|
||||
{time.Second, 2 * time.Second},
|
||||
{2 * time.Second, 3 * time.Second},
|
||||
{4 * time.Second, 5 * time.Second},
|
||||
{8 * time.Second, 9 * time.Second},
|
||||
}
|
||||
for i, test := range tt {
|
||||
d := backoff(i, time.Minute)
|
||||
if d < test.min || test.max < d {
|
||||
t.Errorf("%d: d = %v; want between %v and %v", i, d, test.min, test.max)
|
||||
}
|
||||
}
|
||||
|
||||
min, max := time.Second, 2*time.Second
|
||||
if d := backoff(-1, time.Minute); d < min || max < d {
|
||||
t.Errorf("d = %v; want between %v and %v", d, min, max)
|
||||
}
|
||||
|
||||
bound := 10 * time.Second
|
||||
if d := backoff(100, bound); d != bound {
|
||||
t.Errorf("d = %v; want %v", d, bound)
|
||||
}
|
||||
}
|
||||
776
vendor/golang.org/x/crypto/acme/autocert/autocert.go
сгенерированный
поставляемый
Обычный файл
776
vendor/golang.org/x/crypto/acme/autocert/autocert.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,776 @@
|
||||
// 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"
|
||||
"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"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// pseudoRand is safe for concurrent use.
|
||||
var pseudoRand *lockedMathRand
|
||||
|
||||
func init() {
|
||||
src := mathrand.NewSource(timeNow().UnixNano())
|
||||
pseudoRand = &lockedMathRand{rnd: mathrand.New(src)}
|
||||
}
|
||||
|
||||
// AcceptTOS always returns true to indicate the acceptance of a CA 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.
|
||||
//
|
||||
// A simple usage example:
|
||||
//
|
||||
// m := autocert.Manager{
|
||||
// Prompt: autocert.AcceptTOS,
|
||||
// HostPolicy: autocert.HostWhitelist("example.org"),
|
||||
// }
|
||||
// s := &http.Server{
|
||||
// Addr: ":https",
|
||||
// TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
|
||||
// }
|
||||
// s.ListenAndServeTLS("", "")
|
||||
//
|
||||
// To preserve issued certificates and improve overall performance,
|
||||
// use a cache implementation of Cache. For instance, DirCache.
|
||||
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 1 week 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
|
||||
|
||||
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) {
|
||||
name := hello.ServerName
|
||||
if name == "" {
|
||||
return nil, errors.New("acme/autocert: missing server name")
|
||||
}
|
||||
|
||||
// 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(name); err == nil {
|
||||
return cert, nil
|
||||
}
|
||||
// TODO: cache error results?
|
||||
return nil, fmt.Errorf("acme/autocert: no token cert for %q", name)
|
||||
}
|
||||
|
||||
// regular domain
|
||||
cert, err := m.cert(name)
|
||||
if err == nil {
|
||||
return cert, nil
|
||||
}
|
||||
if err != ErrCacheMiss {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// first-time
|
||||
ctx := context.Background() // TODO: use a deadline?
|
||||
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(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(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(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.
|
||||
func (m *Manager) cacheGet(domain string) (*tls.Certificate, error) {
|
||||
if m.Cache == nil {
|
||||
return nil, ErrCacheMiss
|
||||
}
|
||||
// TODO: might want to define a cache timeout on m
|
||||
ctx := context.Background()
|
||||
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, errors.New("acme/autocert: no private key found in cache")
|
||||
}
|
||||
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 {
|
||||
return nil, errors.New("acme/autocert: invalid public key")
|
||||
}
|
||||
|
||||
// verify and create TLS cert
|
||||
leaf, err := validCert(domain, pubDER, privKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tlscert := &tls.Certificate{
|
||||
Certificate: pubDER,
|
||||
PrivateKey: privKey,
|
||||
Leaf: leaf,
|
||||
}
|
||||
return tlscert, nil
|
||||
}
|
||||
|
||||
func (m *Manager) cachePut(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
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: might want to define a cache timeout on m
|
||||
ctx := context.Background()
|
||||
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 the 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 {
|
||||
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
|
||||
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 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) {
|
||||
// TODO: make m.verify retry or retry m.verify calls here
|
||||
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(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(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(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 > maxRandRenew {
|
||||
return m.RenewBefore
|
||||
}
|
||||
return 7 * 24 * time.Hour // 1 week
|
||||
}
|
||||
|
||||
// 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
|
||||
390
vendor/golang.org/x/crypto/acme/autocert/autocert_test.go
сгенерированный
поставляемый
Обычный файл
390
vendor/golang.org/x/crypto/acme/autocert/autocert_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,390 @@
|
||||
// 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 (
|
||||
"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"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/acme"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
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 map[string][]byte
|
||||
|
||||
func (m memCache) Get(ctx context.Context, key string) ([]byte, error) {
|
||||
v, ok := m[key]
|
||||
if !ok {
|
||||
return nil, ErrCacheMiss
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (m memCache) Put(ctx context.Context, key string, data []byte) error {
|
||||
m[key] = data
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m memCache) Delete(ctx context.Context, key string) error {
|
||||
delete(m, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
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) {
|
||||
const domain = "example.org"
|
||||
man := &Manager{Prompt: AcceptTOS}
|
||||
defer man.stopRenew()
|
||||
|
||||
// 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.Fatalf("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.Fatalf("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.Fatalf("new-cert: CSR: %v", err)
|
||||
}
|
||||
der, err := dummyCert(csr.PublicKey, domain)
|
||||
if err != nil {
|
||||
t.Fatalf("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.Fatalf("ca-cert: dummyCert: %v", err)
|
||||
}
|
||||
w.Write(der)
|
||||
default:
|
||||
t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path)
|
||||
}
|
||||
}))
|
||||
defer ca.Close()
|
||||
|
||||
// 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: ca.URL,
|
||||
}
|
||||
|
||||
// simulate tls.Config.GetCertificate
|
||||
var tlscert *tls.Certificate
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
hello := &tls.ClientHelloInfo{ServerName: domain}
|
||||
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)
|
||||
}
|
||||
|
||||
// make sure token cert was removed
|
||||
done = make(chan struct{})
|
||||
go func() {
|
||||
for {
|
||||
hello := &tls.ClientHelloInfo{ServerName: tokenCertName}
|
||||
if _, err := man.GetCertificate(hello); err != nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
close(done)
|
||||
}()
|
||||
select {
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Error("token cert was not removed")
|
||||
case <-done:
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccountKeyCache(t *testing.T) {
|
||||
cache := make(memCache)
|
||||
m := Manager{Cache: cache}
|
||||
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,
|
||||
}
|
||||
|
||||
cache := make(memCache)
|
||||
man := &Manager{Cache: cache}
|
||||
defer man.stopRenew()
|
||||
if err := man.cachePut("example.org", tlscert); err != nil {
|
||||
t.Fatalf("man.cachePut: %v", err)
|
||||
}
|
||||
res, err := man.cacheGet("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)
|
||||
}
|
||||
}
|
||||
}
|
||||
130
vendor/golang.org/x/crypto/acme/autocert/cache.go
сгенерированный
поставляемый
Обычный файл
130
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 (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// 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.
|
||||
// Inderlying 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
|
||||
}
|
||||
// prevent overwriting the file if the context was cancelled
|
||||
if ctx.Err() != nil {
|
||||
return // no need to set err
|
||||
}
|
||||
name = filepath.Join(string(d), name)
|
||||
err = os.Rename(tmp, name)
|
||||
}()
|
||||
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/golang.org/x/crypto/acme/autocert/cache_test.go
сгенерированный
поставляемый
Обычный файл
58
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 (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// 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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
125
vendor/golang.org/x/crypto/acme/autocert/renewal.go
сгенерированный
поставляемый
Обычный файл
125
vendor/golang.org/x/crypto/acme/autocert/renewal.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,125 @@
|
||||
// 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 (
|
||||
"crypto"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// maxRandRenew is a maximum deviation from Manager.RenewBefore.
|
||||
const maxRandRenew = time.Hour
|
||||
|
||||
// domainRenewal tracks the state used by the periodic timers
|
||||
// renewing a single domain's cert.
|
||||
type domainRenewal struct {
|
||||
m *Manager
|
||||
domain string
|
||||
key crypto.Signer
|
||||
|
||||
timerMu sync.Mutex
|
||||
timer *time.Timer
|
||||
}
|
||||
|
||||
// start starts a cert renewal timer at the time
|
||||
// defined by the certificate expiration time exp.
|
||||
//
|
||||
// If the timer is already started, calling start is a noop.
|
||||
func (dr *domainRenewal) start(exp time.Time) {
|
||||
dr.timerMu.Lock()
|
||||
defer dr.timerMu.Unlock()
|
||||
if dr.timer != nil {
|
||||
return
|
||||
}
|
||||
dr.timer = time.AfterFunc(dr.next(exp), dr.renew)
|
||||
}
|
||||
|
||||
// stop stops the cert renewal timer.
|
||||
// If the timer is already stopped, calling stop is a noop.
|
||||
func (dr *domainRenewal) stop() {
|
||||
dr.timerMu.Lock()
|
||||
defer dr.timerMu.Unlock()
|
||||
if dr.timer == nil {
|
||||
return
|
||||
}
|
||||
dr.timer.Stop()
|
||||
dr.timer = nil
|
||||
}
|
||||
|
||||
// renew is called periodically by a timer.
|
||||
// The first renew call is kicked off by dr.start.
|
||||
func (dr *domainRenewal) renew() {
|
||||
dr.timerMu.Lock()
|
||||
defer dr.timerMu.Unlock()
|
||||
if dr.timer == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
||||
defer cancel()
|
||||
// TODO: rotate dr.key at some point?
|
||||
next, err := dr.do(ctx)
|
||||
if err != nil {
|
||||
next = maxRandRenew / 2
|
||||
next += time.Duration(pseudoRand.int63n(int64(next)))
|
||||
}
|
||||
dr.timer = time.AfterFunc(next, dr.renew)
|
||||
testDidRenewLoop(next, err)
|
||||
}
|
||||
|
||||
// do is similar to Manager.createCert but it doesn't lock a Manager.state item.
|
||||
// Instead, it requests a new certificate independently and, upon success,
|
||||
// replaces dr.m.state item with a new one and updates cache for the given domain.
|
||||
//
|
||||
// It may return immediately if the expiration date of the currently cached cert
|
||||
// is far enough in the future.
|
||||
//
|
||||
// The returned value is a time interval after which the renewal should occur again.
|
||||
func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) {
|
||||
// a race is likely unavoidable in a distributed environment
|
||||
// but we try nonetheless
|
||||
if tlscert, err := dr.m.cacheGet(dr.domain); err == nil {
|
||||
next := dr.next(tlscert.Leaf.NotAfter)
|
||||
if next > dr.m.renewBefore()+maxRandRenew {
|
||||
return next, nil
|
||||
}
|
||||
}
|
||||
|
||||
der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.domain)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
state := &certState{
|
||||
key: dr.key,
|
||||
cert: der,
|
||||
leaf: leaf,
|
||||
}
|
||||
tlscert, err := state.tlscert()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
dr.m.cachePut(dr.domain, tlscert)
|
||||
dr.m.stateMu.Lock()
|
||||
defer dr.m.stateMu.Unlock()
|
||||
// m.state is guaranteed to be non-nil at this point
|
||||
dr.m.state[dr.domain] = state
|
||||
return dr.next(leaf.NotAfter), nil
|
||||
}
|
||||
|
||||
func (dr *domainRenewal) next(expiry time.Time) time.Duration {
|
||||
d := expiry.Sub(timeNow()) - dr.m.renewBefore()
|
||||
// add a bit of randomness to renew deadline
|
||||
n := pseudoRand.int63n(int64(maxRandRenew))
|
||||
d -= time.Duration(n)
|
||||
if d < 0 {
|
||||
return 0
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
var testDidRenewLoop = func(next time.Duration, err error) {}
|
||||
190
vendor/golang.org/x/crypto/acme/autocert/renewal_test.go
сгенерированный
поставляемый
Обычный файл
190
vendor/golang.org/x/crypto/acme/autocert/renewal_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,190 @@
|
||||
// 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 (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/acme"
|
||||
)
|
||||
|
||||
func TestRenewalNext(t *testing.T) {
|
||||
now := time.Now()
|
||||
timeNow = func() time.Time { return now }
|
||||
defer func() { timeNow = time.Now }()
|
||||
|
||||
man := &Manager{RenewBefore: 7 * 24 * time.Hour}
|
||||
defer man.stopRenew()
|
||||
tt := []struct {
|
||||
expiry time.Time
|
||||
min, max time.Duration
|
||||
}{
|
||||
{now.Add(90 * 24 * time.Hour), 83*24*time.Hour - maxRandRenew, 83 * 24 * time.Hour},
|
||||
{now.Add(time.Hour), 0, 1},
|
||||
{now, 0, 1},
|
||||
{now.Add(-time.Hour), 0, 1},
|
||||
}
|
||||
|
||||
dr := &domainRenewal{m: man}
|
||||
for i, test := range tt {
|
||||
next := dr.next(test.expiry)
|
||||
if next < test.min || test.max < next {
|
||||
t.Errorf("%d: next = %v; want between %v and %v", i, next, test.min, test.max)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenewFromCache(t *testing.T) {
|
||||
const domain = "example.org"
|
||||
|
||||
// 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.Fatalf("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)
|
||||
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.Fatalf("new-cert: CSR: %v", err)
|
||||
}
|
||||
der, err := dummyCert(csr.PublicKey, domain)
|
||||
if err != nil {
|
||||
t.Fatalf("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.Fatalf("ca-cert: dummyCert: %v", err)
|
||||
}
|
||||
w.Write(der)
|
||||
default:
|
||||
t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path)
|
||||
}
|
||||
}))
|
||||
defer ca.Close()
|
||||
|
||||
// use EC key to run faster on 386
|
||||
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
man := &Manager{
|
||||
Prompt: AcceptTOS,
|
||||
Cache: make(memCache),
|
||||
RenewBefore: 24 * time.Hour,
|
||||
Client: &acme.Client{
|
||||
Key: key,
|
||||
DirectoryURL: ca.URL,
|
||||
},
|
||||
}
|
||||
defer man.stopRenew()
|
||||
|
||||
// cache an almost expired cert
|
||||
now := time.Now()
|
||||
cert, err := dateDummyCert(key.Public(), now.Add(-2*time.Hour), now.Add(time.Minute), domain)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tlscert := &tls.Certificate{PrivateKey: key, Certificate: [][]byte{cert}}
|
||||
if err := man.cachePut(domain, tlscert); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// veriy the renewal happened
|
||||
defer func() {
|
||||
testDidRenewLoop = func(next time.Duration, err error) {}
|
||||
}()
|
||||
done := make(chan struct{})
|
||||
testDidRenewLoop = func(next time.Duration, err error) {
|
||||
defer close(done)
|
||||
if err != nil {
|
||||
t.Errorf("testDidRenewLoop: %v", err)
|
||||
}
|
||||
// Next should be about 90 days:
|
||||
// dummyCert creates 90days expiry + account for man.RenewBefore.
|
||||
// Previous expiration was within 1 min.
|
||||
future := 88 * 24 * time.Hour
|
||||
if next < future {
|
||||
t.Errorf("testDidRenewLoop: next = %v; want >= %v", next, future)
|
||||
}
|
||||
|
||||
// ensure the new cert is cached
|
||||
after := time.Now().Add(future)
|
||||
tlscert, err := man.cacheGet(domain)
|
||||
if err != nil {
|
||||
t.Fatalf("man.cacheGet: %v", err)
|
||||
}
|
||||
if !tlscert.Leaf.NotAfter.After(after) {
|
||||
t.Errorf("cache leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after)
|
||||
}
|
||||
|
||||
// verify the old cert is also replaced in memory
|
||||
man.stateMu.Lock()
|
||||
defer man.stateMu.Unlock()
|
||||
s := man.state[domain]
|
||||
if s == nil {
|
||||
t.Fatalf("m.state[%q] is nil", domain)
|
||||
}
|
||||
tlscert, err = s.tlscert()
|
||||
if err != nil {
|
||||
t.Fatalf("s.tlscert: %v", err)
|
||||
}
|
||||
if !tlscert.Leaf.NotAfter.After(after) {
|
||||
t.Errorf("state leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after)
|
||||
}
|
||||
}
|
||||
|
||||
// trigger renew
|
||||
hello := &tls.ClientHelloInfo{ServerName: domain}
|
||||
if _, err := man.GetCertificate(hello); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// wait for renew loop
|
||||
select {
|
||||
case <-time.After(10 * time.Second):
|
||||
t.Fatal("renew took too long to occur")
|
||||
case <-done:
|
||||
}
|
||||
}
|
||||
473
vendor/golang.org/x/crypto/acme/internal/acme/acme.go
сгенерированный
поставляемый
473
vendor/golang.org/x/crypto/acme/internal/acme/acme.go
сгенерированный
поставляемый
@@ -1,473 +0,0 @@
|
||||
// Copyright 2015 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 acme provides an ACME client implementation.
|
||||
// See https://ietf-wg-acme.github.io/acme/ for details.
|
||||
//
|
||||
// This package is a work in progress and makes no API stability promises.
|
||||
package acme
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rsa"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// Client is an ACME client.
|
||||
type Client struct {
|
||||
// HTTPClient optionally specifies an HTTP client to use
|
||||
// instead of http.DefaultClient.
|
||||
HTTPClient *http.Client
|
||||
|
||||
// Key is the account key used to register with a CA
|
||||
// and sign requests.
|
||||
Key *rsa.PrivateKey
|
||||
}
|
||||
|
||||
// Discover performs ACME server discovery using the provided discovery endpoint URL.
|
||||
func (c *Client) Discover(url string) (*Directory, error) {
|
||||
res, err := c.httpClient().Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, responseError(res)
|
||||
}
|
||||
var v struct {
|
||||
Reg string `json:"new-reg"`
|
||||
Authz string `json:"new-authz"`
|
||||
Cert string `json:"new-cert"`
|
||||
Revoke string `json:"revoke-cert"`
|
||||
Meta struct {
|
||||
Terms string `json:"terms-of-service"`
|
||||
Website string `json:"website"`
|
||||
CAA []string `json:"caa-identities"`
|
||||
}
|
||||
}
|
||||
if json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Directory{
|
||||
RegURL: v.Reg,
|
||||
AuthzURL: v.Authz,
|
||||
CertURL: v.Cert,
|
||||
RevokeURL: v.Revoke,
|
||||
Terms: v.Meta.Terms,
|
||||
Website: v.Meta.Website,
|
||||
CAA: v.Meta.CAA,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CreateCert requests a new certificate.
|
||||
// In the case where CA server does not provide the issued certificate in the response,
|
||||
// CreateCert will poll certURL using c.FetchCert, which will result in additional round-trips.
|
||||
// In such scenario the caller can cancel the polling with ctx.
|
||||
//
|
||||
// If the bundle is true, the returned value will also contain CA (the issuer) certificate.
|
||||
// The url argument is an Directory.CertURL value, typically obtained from c.Discover.
|
||||
// The csr is a DER encoded certificate signing request.
|
||||
func (c *Client) CreateCert(ctx context.Context, url string, csr []byte, exp time.Duration, bundle bool) (der [][]byte, certURL string, err error) {
|
||||
req := struct {
|
||||
Resource string `json:"resource"`
|
||||
CSR string `json:"csr"`
|
||||
NotBefore string `json:"notBefore,omitempty"`
|
||||
NotAfter string `json:"notAfter,omitempty"`
|
||||
}{
|
||||
Resource: "new-cert",
|
||||
CSR: base64.RawURLEncoding.EncodeToString(csr),
|
||||
}
|
||||
now := timeNow()
|
||||
req.NotBefore = now.Format(time.RFC3339)
|
||||
if exp > 0 {
|
||||
req.NotAfter = now.Add(exp).Format(time.RFC3339)
|
||||
}
|
||||
|
||||
res, err := c.postJWS(url, req)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusCreated {
|
||||
return nil, "", responseError(res)
|
||||
}
|
||||
|
||||
curl := res.Header.Get("location") // cert permanent URL
|
||||
if res.ContentLength == 0 {
|
||||
// no cert in the body; poll until we get it
|
||||
cert, err := c.FetchCert(ctx, curl, bundle)
|
||||
return cert, curl, err
|
||||
}
|
||||
// slurp issued cert and ca, if requested
|
||||
cert, err := responseCert(c.httpClient(), res, bundle)
|
||||
return cert, curl, err
|
||||
}
|
||||
|
||||
// FetchCert retrieves already issued certificate from the given url, in DER format.
|
||||
// It retries the request until the certificate is successfully retrieved,
|
||||
// context is cancelled by the caller or an error response is received.
|
||||
//
|
||||
// The returned value will also contain CA (the issuer) certificate if bundle == true.
|
||||
//
|
||||
// http.DefaultClient is used if client argument is nil.
|
||||
func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) {
|
||||
for {
|
||||
res, err := c.httpClient().Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode == http.StatusOK {
|
||||
return responseCert(c.httpClient(), res, bundle)
|
||||
}
|
||||
if res.StatusCode > 299 {
|
||||
return nil, responseError(res)
|
||||
}
|
||||
d, err := retryAfter(res.Header.Get("retry-after"))
|
||||
if err != nil {
|
||||
d = 3 * time.Second
|
||||
}
|
||||
select {
|
||||
case <-time.After(d):
|
||||
// retry
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register creates a new account registration by following the "new-reg" flow.
|
||||
// It returns registered account. The a argument is not modified.
|
||||
//
|
||||
// The url argument is typically an Directory.RegURL obtained from c.Discover.
|
||||
func (c *Client) Register(url string, a *Account) (*Account, error) {
|
||||
return c.doReg(url, "new-reg", a)
|
||||
}
|
||||
|
||||
// GetReg retrieves an existing registration.
|
||||
// The url argument is an Account.URI, typically obtained from c.Register.
|
||||
func (c *Client) GetReg(url string) (*Account, error) {
|
||||
a := &Account{URI: url}
|
||||
return c.doReg(url, "reg", a)
|
||||
}
|
||||
|
||||
// UpdateReg updates an existing registration.
|
||||
// It returns an updated account copy. The provided account is not modified.
|
||||
//
|
||||
// The url argument is an Account.URI, usually obtained with c.Register.
|
||||
func (c *Client) UpdateReg(url string, a *Account) (*Account, error) {
|
||||
return c.doReg(url, "reg", a)
|
||||
}
|
||||
|
||||
// Authorize performs the initial step in an authorization flow.
|
||||
// The caller will then need to choose from and perform a set of returned
|
||||
// challenges using c.Accept in order to successfully complete authorization.
|
||||
//
|
||||
// The url argument is an authz URL, usually obtained with c.Register.
|
||||
func (c *Client) Authorize(url, domain string) (*Authorization, error) {
|
||||
type authzID struct {
|
||||
Type string `json:"type"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
req := struct {
|
||||
Resource string `json:"resource"`
|
||||
Identifier authzID `json:"identifier"`
|
||||
}{
|
||||
Resource: "new-authz",
|
||||
Identifier: authzID{Type: "dns", Value: domain},
|
||||
}
|
||||
res, err := c.postJWS(url, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusCreated {
|
||||
return nil, responseError(res)
|
||||
}
|
||||
|
||||
var v wireAuthz
|
||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||
return nil, fmt.Errorf("Decode: %v", err)
|
||||
}
|
||||
if v.Status != StatusPending {
|
||||
return nil, fmt.Errorf("Unexpected status: %s", v.Status)
|
||||
}
|
||||
return v.authorization(res.Header.Get("Location")), nil
|
||||
}
|
||||
|
||||
// GetAuthz retrieves the current status of an authorization flow.
|
||||
//
|
||||
// A client typically polls an authz status using this method.
|
||||
func (c *Client) GetAuthz(url string) (*Authorization, error) {
|
||||
res, err := c.httpClient().Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
|
||||
return nil, responseError(res)
|
||||
}
|
||||
var v wireAuthz
|
||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||
return nil, fmt.Errorf("Decode: %v", err)
|
||||
}
|
||||
return v.authorization(url), nil
|
||||
}
|
||||
|
||||
// GetChallenge retrieves the current status of an challenge.
|
||||
//
|
||||
// A client typically polls a challenge status using this method.
|
||||
func (c *Client) GetChallenge(url string) (*Challenge, error) {
|
||||
res, err := c.httpClient().Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
|
||||
return nil, responseError(res)
|
||||
}
|
||||
v := wireChallenge{URI: url}
|
||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||
return nil, fmt.Errorf("Decode: %v", err)
|
||||
}
|
||||
return v.challenge(), nil
|
||||
}
|
||||
|
||||
// Accept informs the server that the client accepts one of its challenges
|
||||
// previously obtained with c.Authorize.
|
||||
//
|
||||
// The server will then perform the validation asynchronously.
|
||||
func (c *Client) Accept(chal *Challenge) (*Challenge, error) {
|
||||
req := struct {
|
||||
Resource string `json:"resource"`
|
||||
Type string `json:"type"`
|
||||
Auth string `json:"keyAuthorization"`
|
||||
}{
|
||||
Resource: "challenge",
|
||||
Type: chal.Type,
|
||||
Auth: keyAuth(&c.Key.PublicKey, chal.Token),
|
||||
}
|
||||
res, err := c.postJWS(chal.URI, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
// Note: the protocol specifies 200 as the expected response code, but
|
||||
// letsencrypt seems to be returning 202.
|
||||
if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
|
||||
return nil, responseError(res)
|
||||
}
|
||||
|
||||
var v wireChallenge
|
||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||
return nil, fmt.Errorf("Decode: %v", err)
|
||||
}
|
||||
return v.challenge(), nil
|
||||
}
|
||||
|
||||
// HTTP01Handler creates a new handler which responds to a http-01 challenge.
|
||||
// The token argument is a Challenge.Token value.
|
||||
func (c *Client) HTTP01Handler(token string) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if !strings.HasSuffix(r.URL.Path, token) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
w.Header().Set("content-type", "text/plain")
|
||||
w.Write([]byte(keyAuth(&c.Key.PublicKey, token)))
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Client) httpClient() *http.Client {
|
||||
if c.HTTPClient != nil {
|
||||
return c.HTTPClient
|
||||
}
|
||||
return http.DefaultClient
|
||||
}
|
||||
|
||||
// postJWS signs body and posts it to the provided url.
|
||||
// The body argument must be JSON-serializable.
|
||||
func (c *Client) postJWS(url string, body interface{}) (*http.Response, error) {
|
||||
nonce, err := fetchNonce(c.httpClient(), url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b, err := jwsEncodeJSON(body, c.Key, nonce)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req, err := http.NewRequest("POST", url, bytes.NewReader(b))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.httpClient().Do(req)
|
||||
}
|
||||
|
||||
// doReg sends all types of registration requests.
|
||||
// The type of request is identified by typ argument, which is a "resource"
|
||||
// in the ACME spec terms.
|
||||
//
|
||||
// A non-nil acct argument indicates whether the intention is to mutate data
|
||||
// of the Account. Only Contact and Agreement of its fields are used
|
||||
// in such cases.
|
||||
//
|
||||
// The fields of acct will be populate with the server response
|
||||
// and may be overwritten.
|
||||
func (c *Client) doReg(url string, typ string, acct *Account) (*Account, error) {
|
||||
req := struct {
|
||||
Resource string `json:"resource"`
|
||||
Contact []string `json:"contact,omitempty"`
|
||||
Agreement string `json:"agreement,omitempty"`
|
||||
}{
|
||||
Resource: typ,
|
||||
}
|
||||
if acct != nil {
|
||||
req.Contact = acct.Contact
|
||||
req.Agreement = acct.AgreedTerms
|
||||
}
|
||||
res, err := c.postJWS(url, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode < 200 || res.StatusCode > 299 {
|
||||
return nil, responseError(res)
|
||||
}
|
||||
|
||||
var v struct {
|
||||
Contact []string
|
||||
Agreement string
|
||||
Authorizations string
|
||||
Certificates string
|
||||
}
|
||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||
return nil, fmt.Errorf("Decode: %v", err)
|
||||
}
|
||||
return &Account{
|
||||
URI: res.Header.Get("Location"),
|
||||
Contact: v.Contact,
|
||||
AgreedTerms: v.Agreement,
|
||||
CurrentTerms: linkHeader(res.Header, "terms-of-service"),
|
||||
Authz: linkHeader(res.Header, "next"),
|
||||
Authorizations: v.Authorizations,
|
||||
Certificates: v.Certificates,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func responseCert(client *http.Client, res *http.Response, bundle bool) ([][]byte, error) {
|
||||
b, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ReadAll: %v", err)
|
||||
}
|
||||
cert := [][]byte{b}
|
||||
if !bundle {
|
||||
return cert, nil
|
||||
}
|
||||
|
||||
// append ca cert
|
||||
up := linkHeader(res.Header, "up")
|
||||
if up == "" {
|
||||
return nil, errors.New("rel=up link not found")
|
||||
}
|
||||
res, err = client.Get(up)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, responseError(res)
|
||||
}
|
||||
b, err = ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(cert, b), nil
|
||||
}
|
||||
|
||||
// responseError creates an error of Error type from resp.
|
||||
func responseError(resp *http.Response) error {
|
||||
// don't care if ReadAll returns an error:
|
||||
// json.Unmarshal will fail in that case anyway
|
||||
b, _ := ioutil.ReadAll(resp.Body)
|
||||
e := struct {
|
||||
Status int
|
||||
Type string
|
||||
Detail string
|
||||
}{
|
||||
Status: resp.StatusCode,
|
||||
}
|
||||
if err := json.Unmarshal(b, &e); err != nil {
|
||||
// this is not a regular error response:
|
||||
// populate detail with anything we received,
|
||||
// e.Status will already contain HTTP response code value
|
||||
e.Detail = string(b)
|
||||
if e.Detail == "" {
|
||||
e.Detail = resp.Status
|
||||
}
|
||||
}
|
||||
return &Error{
|
||||
StatusCode: e.Status,
|
||||
ProblemType: e.Type,
|
||||
Detail: e.Detail,
|
||||
Header: resp.Header,
|
||||
}
|
||||
}
|
||||
|
||||
func fetchNonce(client *http.Client, url string) (string, error) {
|
||||
resp, err := client.Head(url)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
enc := resp.Header.Get("replay-nonce")
|
||||
if enc == "" {
|
||||
return "", errors.New("nonce not found")
|
||||
}
|
||||
return enc, nil
|
||||
}
|
||||
|
||||
func linkHeader(h http.Header, rel string) string {
|
||||
for _, v := range h["Link"] {
|
||||
parts := strings.Split(v, ";")
|
||||
for _, p := range parts {
|
||||
p = strings.TrimSpace(p)
|
||||
if !strings.HasPrefix(p, "rel=") {
|
||||
continue
|
||||
}
|
||||
if v := strings.Trim(p[4:], `"`); v == rel {
|
||||
return strings.Trim(parts[0], "<>")
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func retryAfter(v string) (time.Duration, error) {
|
||||
if i, err := strconv.Atoi(v); err == nil {
|
||||
return time.Duration(i) * time.Second, nil
|
||||
}
|
||||
t, err := http.ParseTime(v)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return t.Sub(timeNow()), nil
|
||||
}
|
||||
|
||||
// keyAuth generates a key authorization string for a given token.
|
||||
func keyAuth(pub *rsa.PublicKey, token string) string {
|
||||
return fmt.Sprintf("%s.%s", token, JWKThumbprint(pub))
|
||||
}
|
||||
|
||||
// timeNow is useful for testing for fixed current time.
|
||||
var timeNow = time.Now
|
||||
67
vendor/golang.org/x/crypto/acme/internal/acme/jws.go
сгенерированный
поставляемый
67
vendor/golang.org/x/crypto/acme/internal/acme/jws.go
сгенерированный
поставляемый
@@ -1,67 +0,0 @@
|
||||
// Copyright 2015 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 acme
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// jwsEncodeJSON signs claimset using provided key and a nonce.
|
||||
// The result is serialized in JSON format.
|
||||
// See https://tools.ietf.org/html/rfc7515#section-7.
|
||||
func jwsEncodeJSON(claimset interface{}, key *rsa.PrivateKey, nonce string) ([]byte, error) {
|
||||
jwk := jwkEncode(&key.PublicKey)
|
||||
phead := fmt.Sprintf(`{"alg":"RS256","jwk":%s,"nonce":%q}`, jwk, nonce)
|
||||
phead = base64.RawURLEncoding.EncodeToString([]byte(phead))
|
||||
cs, err := json.Marshal(claimset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payload := base64.RawURLEncoding.EncodeToString(cs)
|
||||
h := sha256.New()
|
||||
h.Write([]byte(phead + "." + payload))
|
||||
sig, err := rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, h.Sum(nil))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
enc := struct {
|
||||
Protected string `json:"protected"`
|
||||
Payload string `json:"payload"`
|
||||
Sig string `json:"signature"`
|
||||
}{
|
||||
Protected: phead,
|
||||
Payload: payload,
|
||||
Sig: base64.RawURLEncoding.EncodeToString(sig),
|
||||
}
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
// jwkEncode encodes public part of an RSA key into a JWK.
|
||||
// The result is also suitable for creating a JWK thumbprint.
|
||||
func jwkEncode(pub *rsa.PublicKey) string {
|
||||
n := pub.N
|
||||
e := big.NewInt(int64(pub.E))
|
||||
// fields order is important
|
||||
// see https://tools.ietf.org/html/rfc7638#section-3.3 for details
|
||||
return fmt.Sprintf(`{"e":"%s","kty":"RSA","n":"%s"}`,
|
||||
base64.RawURLEncoding.EncodeToString(e.Bytes()),
|
||||
base64.RawURLEncoding.EncodeToString(n.Bytes()),
|
||||
)
|
||||
}
|
||||
|
||||
// JWKThumbprint creates a JWK thumbprint out of pub
|
||||
// as specified in https://tools.ietf.org/html/rfc7638.
|
||||
func JWKThumbprint(pub *rsa.PublicKey) string {
|
||||
jwk := jwkEncode(pub)
|
||||
b := sha256.Sum256([]byte(jwk))
|
||||
return base64.RawURLEncoding.EncodeToString(b[:])
|
||||
}
|
||||
153
vendor/golang.org/x/crypto/acme/jws.go
сгенерированный
поставляемый
Обычный файл
153
vendor/golang.org/x/crypto/acme/jws.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,153 @@
|
||||
// Copyright 2015 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 acme
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
_ "crypto/sha512" // need for EC keys
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// jwsEncodeJSON signs claimset using provided key and a nonce.
|
||||
// The result is serialized in JSON format.
|
||||
// See https://tools.ietf.org/html/rfc7515#section-7.
|
||||
func jwsEncodeJSON(claimset interface{}, key crypto.Signer, nonce string) ([]byte, error) {
|
||||
jwk, err := jwkEncode(key.Public())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
alg, sha := jwsHasher(key)
|
||||
if alg == "" || !sha.Available() {
|
||||
return nil, ErrUnsupportedKey
|
||||
}
|
||||
phead := fmt.Sprintf(`{"alg":%q,"jwk":%s,"nonce":%q}`, alg, jwk, nonce)
|
||||
phead = base64.RawURLEncoding.EncodeToString([]byte(phead))
|
||||
cs, err := json.Marshal(claimset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payload := base64.RawURLEncoding.EncodeToString(cs)
|
||||
hash := sha.New()
|
||||
hash.Write([]byte(phead + "." + payload))
|
||||
sig, err := jwsSign(key, sha, hash.Sum(nil))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
enc := struct {
|
||||
Protected string `json:"protected"`
|
||||
Payload string `json:"payload"`
|
||||
Sig string `json:"signature"`
|
||||
}{
|
||||
Protected: phead,
|
||||
Payload: payload,
|
||||
Sig: base64.RawURLEncoding.EncodeToString(sig),
|
||||
}
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
// jwkEncode encodes public part of an RSA or ECDSA key into a JWK.
|
||||
// The result is also suitable for creating a JWK thumbprint.
|
||||
// https://tools.ietf.org/html/rfc7517
|
||||
func jwkEncode(pub crypto.PublicKey) (string, error) {
|
||||
switch pub := pub.(type) {
|
||||
case *rsa.PublicKey:
|
||||
// https://tools.ietf.org/html/rfc7518#section-6.3.1
|
||||
n := pub.N
|
||||
e := big.NewInt(int64(pub.E))
|
||||
// Field order is important.
|
||||
// See https://tools.ietf.org/html/rfc7638#section-3.3 for details.
|
||||
return fmt.Sprintf(`{"e":"%s","kty":"RSA","n":"%s"}`,
|
||||
base64.RawURLEncoding.EncodeToString(e.Bytes()),
|
||||
base64.RawURLEncoding.EncodeToString(n.Bytes()),
|
||||
), nil
|
||||
case *ecdsa.PublicKey:
|
||||
// https://tools.ietf.org/html/rfc7518#section-6.2.1
|
||||
p := pub.Curve.Params()
|
||||
n := p.BitSize / 8
|
||||
if p.BitSize%8 != 0 {
|
||||
n++
|
||||
}
|
||||
x := pub.X.Bytes()
|
||||
if n > len(x) {
|
||||
x = append(make([]byte, n-len(x)), x...)
|
||||
}
|
||||
y := pub.Y.Bytes()
|
||||
if n > len(y) {
|
||||
y = append(make([]byte, n-len(y)), y...)
|
||||
}
|
||||
// Field order is important.
|
||||
// See https://tools.ietf.org/html/rfc7638#section-3.3 for details.
|
||||
return fmt.Sprintf(`{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`,
|
||||
p.Name,
|
||||
base64.RawURLEncoding.EncodeToString(x),
|
||||
base64.RawURLEncoding.EncodeToString(y),
|
||||
), nil
|
||||
}
|
||||
return "", ErrUnsupportedKey
|
||||
}
|
||||
|
||||
// jwsSign signs the digest using the given key.
|
||||
// It returns ErrUnsupportedKey if the key type is unknown.
|
||||
// The hash is used only for RSA keys.
|
||||
func jwsSign(key crypto.Signer, hash crypto.Hash, digest []byte) ([]byte, error) {
|
||||
switch key := key.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
return key.Sign(rand.Reader, digest, hash)
|
||||
case *ecdsa.PrivateKey:
|
||||
r, s, err := ecdsa.Sign(rand.Reader, key, digest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rb, sb := r.Bytes(), s.Bytes()
|
||||
size := key.Params().BitSize / 8
|
||||
if size%8 > 0 {
|
||||
size++
|
||||
}
|
||||
sig := make([]byte, size*2)
|
||||
copy(sig[size-len(rb):], rb)
|
||||
copy(sig[size*2-len(sb):], sb)
|
||||
return sig, nil
|
||||
}
|
||||
return nil, ErrUnsupportedKey
|
||||
}
|
||||
|
||||
// jwsHasher indicates suitable JWS algorithm name and a hash function
|
||||
// to use for signing a digest with the provided key.
|
||||
// It returns ("", 0) if the key is not supported.
|
||||
func jwsHasher(key crypto.Signer) (string, crypto.Hash) {
|
||||
switch key := key.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
return "RS256", crypto.SHA256
|
||||
case *ecdsa.PrivateKey:
|
||||
switch key.Params().Name {
|
||||
case "P-256":
|
||||
return "ES256", crypto.SHA256
|
||||
case "P-384":
|
||||
return "ES384", crypto.SHA384
|
||||
case "P-512":
|
||||
return "ES512", crypto.SHA512
|
||||
}
|
||||
}
|
||||
return "", 0
|
||||
}
|
||||
|
||||
// JWKThumbprint creates a JWK thumbprint out of pub
|
||||
// as specified in https://tools.ietf.org/html/rfc7638.
|
||||
func JWKThumbprint(pub crypto.PublicKey) (string, error) {
|
||||
jwk, err := jwkEncode(pub)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
b := sha256.Sum256([]byte(jwk))
|
||||
return base64.RawURLEncoding.EncodeToString(b[:]), nil
|
||||
}
|
||||
143
vendor/golang.org/x/crypto/acme/internal/acme/jws_test.go → vendor/golang.org/x/crypto/acme/jws_test.go
сгенерированный
поставляемый
143
vendor/golang.org/x/crypto/acme/internal/acme/jws_test.go → vendor/golang.org/x/crypto/acme/jws_test.go
сгенерированный
поставляемый
@@ -5,6 +5,8 @@
|
||||
package acme
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
@@ -47,7 +49,29 @@ EQeIP6dZtv8IMgtGIb91QX9pXvP0aznzQKwYIA8nZgoENCPfiMTPiEDT9e/0lObO
|
||||
// This thumbprint is for the testKey defined above.
|
||||
const testKeyThumbprint = "6nicxzh6WETQlrvdchkz-U3e3DOQZ4heJKU63rfqMqQ"
|
||||
|
||||
var testKey *rsa.PrivateKey
|
||||
const (
|
||||
// openssl ecparam -name secp256k1 -genkey -noout
|
||||
testKeyECPEM = `
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIK07hGLr0RwyUdYJ8wbIiBS55CjnkMD23DWr+ccnypWLoAoGCCqGSM49
|
||||
AwEHoUQDQgAE5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HThqIrvawF5
|
||||
QAaS/RNouybCiRhRjI3EaxLkQwgrCw0gqQ==
|
||||
-----END EC PRIVATE KEY-----
|
||||
`
|
||||
// 1. opnessl ec -in key.pem -noout -text
|
||||
// 2. remove first byte, 04 (the header); the rest is X and Y
|
||||
// 3. covert each with: echo <val> | xxd -r -p | base64 | tr -d '=' | tr '/+' '_-'
|
||||
testKeyECPubX = "5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HQ"
|
||||
testKeyECPubY = "4aiK72sBeUAGkv0TaLsmwokYUYyNxGsS5EMIKwsNIKk"
|
||||
// echo -n '{"crv":"P-256","kty":"EC","x":"<testKeyECPubX>","y":"<testKeyECPubY>"}' | \
|
||||
// openssl dgst -binary -sha256 | base64 | tr -d '=' | tr '/+' '_-'
|
||||
testKeyECThumbprint = "zedj-Bd1Zshp8KLePv2MB-lJ_Hagp7wAwdkA0NUTniU"
|
||||
)
|
||||
|
||||
var (
|
||||
testKey *rsa.PrivateKey
|
||||
testKeyEC *ecdsa.PrivateKey
|
||||
)
|
||||
|
||||
func init() {
|
||||
d, _ := pem.Decode([]byte(testKeyPEM))
|
||||
@@ -59,6 +83,14 @@ func init() {
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
if d, _ = pem.Decode([]byte(testKeyECPEM)); d == nil {
|
||||
panic("no block found in testKeyECPEM")
|
||||
}
|
||||
testKeyEC, err = x509.ParseECPrivateKey(d.Bytes)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestJWSEncodeJSON(t *testing.T) {
|
||||
@@ -108,7 +140,55 @@ func TestJWSEncodeJSON(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestJWKThumbprint(t *testing.T) {
|
||||
func TestJWSEncodeJSONEC(t *testing.T) {
|
||||
claims := struct{ Msg string }{"Hello JWS"}
|
||||
|
||||
b, err := jwsEncodeJSON(claims, testKeyEC, "nonce")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var jws struct{ Protected, Payload, Signature string }
|
||||
if err := json.Unmarshal(b, &jws); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if b, err = base64.RawURLEncoding.DecodeString(jws.Protected); err != nil {
|
||||
t.Fatalf("jws.Protected: %v", err)
|
||||
}
|
||||
var head struct {
|
||||
Alg string
|
||||
Nonce string
|
||||
JWK struct {
|
||||
Crv string
|
||||
Kty string
|
||||
X string
|
||||
Y string
|
||||
} `json:"jwk"`
|
||||
}
|
||||
if err := json.Unmarshal(b, &head); err != nil {
|
||||
t.Fatalf("jws.Protected: %v", err)
|
||||
}
|
||||
if head.Alg != "ES256" {
|
||||
t.Errorf("head.Alg = %q; want ES256", head.Alg)
|
||||
}
|
||||
if head.Nonce != "nonce" {
|
||||
t.Errorf("head.Nonce = %q; want nonce", head.Nonce)
|
||||
}
|
||||
if head.JWK.Crv != "P-256" {
|
||||
t.Errorf("head.JWK.Crv = %q; want P-256", head.JWK.Crv)
|
||||
}
|
||||
if head.JWK.Kty != "EC" {
|
||||
t.Errorf("head.JWK.Kty = %q; want EC", head.JWK.Kty)
|
||||
}
|
||||
if head.JWK.X != testKeyECPubX {
|
||||
t.Errorf("head.JWK.X = %q; want %q", head.JWK.X, testKeyECPubX)
|
||||
}
|
||||
if head.JWK.Y != testKeyECPubY {
|
||||
t.Errorf("head.JWK.Y = %q; want %q", head.JWK.Y, testKeyECPubY)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJWKThumbprintRSA(t *testing.T) {
|
||||
// Key example from RFC 7638
|
||||
const base64N = "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAt" +
|
||||
"VT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn6" +
|
||||
@@ -119,21 +199,68 @@ func TestJWKThumbprint(t *testing.T) {
|
||||
const base64E = "AQAB"
|
||||
const expected = "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs"
|
||||
|
||||
bytes, err := base64.RawURLEncoding.DecodeString(base64N)
|
||||
b, err := base64.RawURLEncoding.DecodeString(base64N)
|
||||
if err != nil {
|
||||
t.Fatalf("Error parsing example key N: %v", err)
|
||||
}
|
||||
n := new(big.Int).SetBytes(bytes)
|
||||
n := new(big.Int).SetBytes(b)
|
||||
|
||||
bytes, err = base64.RawURLEncoding.DecodeString(base64E)
|
||||
b, err = base64.RawURLEncoding.DecodeString(base64E)
|
||||
if err != nil {
|
||||
t.Fatalf("Error parsing example key E: %v", err)
|
||||
}
|
||||
e := new(big.Int).SetBytes(bytes)
|
||||
e := new(big.Int).SetBytes(b)
|
||||
|
||||
pub := &rsa.PublicKey{N: n, E: int(e.Uint64())}
|
||||
th := JWKThumbprint(pub)
|
||||
th, err := JWKThumbprint(pub)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if th != expected {
|
||||
t.Errorf("th = %q; want %q", th, expected)
|
||||
t.Errorf("thumbprint = %q; want %q", th, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJWKThumbprintEC(t *testing.T) {
|
||||
// Key example from RFC 7520
|
||||
// expected was computed with
|
||||
// echo -n '{"crv":"P-521","kty":"EC","x":"<base64X>","y":"<base64Y>"}' | \
|
||||
// openssl dgst -binary -sha256 | \
|
||||
// base64 | \
|
||||
// tr -d '=' | tr '/+' '_-'
|
||||
const (
|
||||
base64X = "AHKZLLOsCOzz5cY97ewNUajB957y-C-U88c3v13nmGZx6sYl_oJXu9A5RkT" +
|
||||
"KqjqvjyekWF-7ytDyRXYgCF5cj0Kt"
|
||||
base64Y = "AdymlHvOiLxXkEhayXQnNCvDX4h9htZaCJN34kfmC6pV5OhQHiraVySsUda" +
|
||||
"QkAgDPrwQrJmbnX9cwlGfP-HqHZR1"
|
||||
expected = "dHri3SADZkrush5HU_50AoRhcKFryN-PI6jPBtPL55M"
|
||||
)
|
||||
|
||||
b, err := base64.RawURLEncoding.DecodeString(base64X)
|
||||
if err != nil {
|
||||
t.Fatalf("Error parsing example key X: %v", err)
|
||||
}
|
||||
x := new(big.Int).SetBytes(b)
|
||||
|
||||
b, err = base64.RawURLEncoding.DecodeString(base64Y)
|
||||
if err != nil {
|
||||
t.Fatalf("Error parsing example key Y: %v", err)
|
||||
}
|
||||
y := new(big.Int).SetBytes(b)
|
||||
|
||||
pub := &ecdsa.PublicKey{Curve: elliptic.P521(), X: x, Y: y}
|
||||
th, err := JWKThumbprint(pub)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if th != expected {
|
||||
t.Errorf("thumbprint = %q; want %q", th, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJWKThumbprintErrUnsupportedKey(t *testing.T) {
|
||||
_, err := JWKThumbprint(struct{}{})
|
||||
if err != ErrUnsupportedKey {
|
||||
t.Errorf("err = %q; want %q", err, ErrUnsupportedKey)
|
||||
}
|
||||
}
|
||||
66
vendor/golang.org/x/crypto/acme/internal/acme/types.go → vendor/golang.org/x/crypto/acme/types.go
сгенерированный
поставляемый
66
vendor/golang.org/x/crypto/acme/internal/acme/types.go → vendor/golang.org/x/crypto/acme/types.go
сгенерированный
поставляемый
@@ -1,6 +1,7 @@
|
||||
package acme
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
@@ -15,6 +16,50 @@ const (
|
||||
StatusRevoked = "revoked"
|
||||
)
|
||||
|
||||
// CRLReasonCode identifies the reason for a certificate revocation.
|
||||
type CRLReasonCode int
|
||||
|
||||
// CRL reason codes as defined in RFC 5280.
|
||||
const (
|
||||
CRLReasonUnspecified CRLReasonCode = 0
|
||||
CRLReasonKeyCompromise CRLReasonCode = 1
|
||||
CRLReasonCACompromise CRLReasonCode = 2
|
||||
CRLReasonAffiliationChanged CRLReasonCode = 3
|
||||
CRLReasonSuperseded CRLReasonCode = 4
|
||||
CRLReasonCessationOfOperation CRLReasonCode = 5
|
||||
CRLReasonCertificateHold CRLReasonCode = 6
|
||||
CRLReasonRemoveFromCRL CRLReasonCode = 8
|
||||
CRLReasonPrivilegeWithdrawn CRLReasonCode = 9
|
||||
CRLReasonAACompromise CRLReasonCode = 10
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrAuthorizationFailed indicates that an authorization for an identifier
|
||||
// did not succeed.
|
||||
ErrAuthorizationFailed = errors.New("acme: identifier authorization failed")
|
||||
|
||||
// ErrUnsupportedKey is returned when an unsupported key type is encountered.
|
||||
ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported")
|
||||
)
|
||||
|
||||
// Error is an ACME error, defined in Problem Details for HTTP APIs doc
|
||||
// http://tools.ietf.org/html/draft-ietf-appsawg-http-problem.
|
||||
type Error struct {
|
||||
// StatusCode is The HTTP status code generated by the origin server.
|
||||
StatusCode int
|
||||
// ProblemType is a URI reference that identifies the problem type,
|
||||
// typically in a "urn:acme:error:xxx" form.
|
||||
ProblemType string
|
||||
// Detail is a human-readable explanation specific to this occurrence of the problem.
|
||||
Detail string
|
||||
// Header is the original server error response headers.
|
||||
Header http.Header
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
return fmt.Sprintf("%d %s: %s", e.StatusCode, e.ProblemType, e.Detail)
|
||||
}
|
||||
|
||||
// Account is a user account. It is associated with a private key.
|
||||
type Account struct {
|
||||
// URI is the account unique ID, which is also a URL used to retrieve
|
||||
@@ -25,7 +70,8 @@ type Account struct {
|
||||
Contact []string
|
||||
|
||||
// The terms user has agreed to.
|
||||
// Zero value indicates that the user hasn't agreed yet.
|
||||
// A value not matching CurrentTerms indicates that the user hasn't agreed
|
||||
// to the actual Terms of Service of the CA.
|
||||
AgreedTerms string
|
||||
|
||||
// Actual terms of a CA.
|
||||
@@ -116,24 +162,6 @@ type AuthzID struct {
|
||||
Value string // The identifier itself, e.g. "example.org".
|
||||
}
|
||||
|
||||
// Error is an ACME error, defined in Problem Details for HTTP APIs doc
|
||||
// http://tools.ietf.org/html/draft-ietf-appsawg-http-problem.
|
||||
type Error struct {
|
||||
// StatusCode is The HTTP status code generated by the origin server.
|
||||
StatusCode int
|
||||
// ProblemType is a URI reference that identifies the problem type,
|
||||
// typically in a "urn:acme:error:xxx" form.
|
||||
ProblemType string
|
||||
// Detail is a human-readable explanation specific to this occurrence of the problem.
|
||||
Detail string
|
||||
// Header is the original server error response headers.
|
||||
Header http.Header
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
return fmt.Sprintf("%d %s: %s", e.StatusCode, e.ProblemType, e.Detail)
|
||||
}
|
||||
|
||||
// wireAuthz is ACME JSON representation of Authorization objects.
|
||||
type wireAuthz struct {
|
||||
Status string
|
||||
2
vendor/golang.org/x/crypto/blowfish/cipher.go
сгенерированный
поставляемый
2
vendor/golang.org/x/crypto/blowfish/cipher.go
сгенерированный
поставляемый
@@ -39,7 +39,7 @@ func NewCipher(key []byte) (*Cipher, error) {
|
||||
|
||||
// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
|
||||
// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
|
||||
// sufficient and desirable. For bcrypt compatiblity, the key can be over 56
|
||||
// sufficient and desirable. For bcrypt compatibility, the key can be over 56
|
||||
// bytes.
|
||||
func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
|
||||
if len(salt) == 0 {
|
||||
|
||||
5
vendor/golang.org/x/crypto/nacl/box/box.go
сгенерированный
поставляемый
5
vendor/golang.org/x/crypto/nacl/box/box.go
сгенерированный
поставляемый
@@ -13,15 +13,16 @@ example, by using nonce 1 for the first message, nonce 2 for the second
|
||||
message, etc. Nonces are long enough that randomly generated nonces have
|
||||
negligible risk of collision.
|
||||
|
||||
This package is interoperable with NaCl: http://nacl.cr.yp.to/box.html.
|
||||
This package is interoperable with NaCl: https://nacl.cr.yp.to/box.html.
|
||||
*/
|
||||
package box // import "golang.org/x/crypto/nacl/box"
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/curve25519"
|
||||
"golang.org/x/crypto/nacl/secretbox"
|
||||
"golang.org/x/crypto/salsa20/salsa"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Overhead is the number of bytes of overhead when boxing a message.
|
||||
|
||||
53
vendor/golang.org/x/crypto/nacl/secretbox/example_test.go
сгенерированный
поставляемый
Обычный файл
53
vendor/golang.org/x/crypto/nacl/secretbox/example_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,53 @@
|
||||
// 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 secretbox_test
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/nacl/secretbox"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
// Load your secret key from a safe place and reuse it across multiple
|
||||
// Seal calls. (Obviously don't use this example key for anything
|
||||
// real.) If you want to convert a passphrase to a key, use a suitable
|
||||
// package like bcrypt or scrypt.
|
||||
secretKeyBytes, err := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var secretKey [32]byte
|
||||
copy(secretKey[:], secretKeyBytes)
|
||||
|
||||
// You must use a different nonce for each message you encrypt with the
|
||||
// same key. Since the nonce here is 192 bits long, a random value
|
||||
// provides a sufficiently small probability of repeats.
|
||||
var nonce [24]byte
|
||||
if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// This encrypts "hello world" and appends the result to the nonce.
|
||||
encrypted := secretbox.Seal(nonce[:], []byte("hello world"), &nonce, &secretKey)
|
||||
|
||||
// When you decrypt, you must use the same nonce and key you used to
|
||||
// encrypt the message. One way to achieve this is to store the nonce
|
||||
// alongside the encrypted message. Above, we stored the nonce in the first
|
||||
// 24 bytes of the encrypted text.
|
||||
var decryptNonce [24]byte
|
||||
copy(decryptNonce[:], encrypted[:24])
|
||||
decrypted, ok := secretbox.Open([]byte{}, encrypted[24:], &decryptNonce, &secretKey)
|
||||
if !ok {
|
||||
panic("decryption error")
|
||||
}
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
// Output: hello world
|
||||
}
|
||||
2
vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go
сгенерированный
поставляемый
2
vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go
сгенерированный
поставляемый
@@ -13,7 +13,7 @@ example, by using nonce 1 for the first message, nonce 2 for the second
|
||||
message, etc. Nonces are long enough that randomly generated nonces have
|
||||
negligible risk of collision.
|
||||
|
||||
This package is interoperable with NaCl: http://nacl.cr.yp.to/secretbox.html.
|
||||
This package is interoperable with NaCl: https://nacl.cr.yp.to/secretbox.html.
|
||||
*/
|
||||
package secretbox // import "golang.org/x/crypto/nacl/secretbox"
|
||||
|
||||
|
||||
12
vendor/golang.org/x/crypto/ocsp/ocsp.go
сгенерированный
поставляемый
12
vendor/golang.org/x/crypto/ocsp/ocsp.go
сгенерированный
поставляемый
@@ -30,11 +30,11 @@ var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1}
|
||||
type ResponseStatus int
|
||||
|
||||
const (
|
||||
Success ResponseStatus = 0
|
||||
Malformed ResponseStatus = 1
|
||||
InternalError ResponseStatus = 2
|
||||
TryLater ResponseStatus = 3
|
||||
// Status code four is ununsed in OCSP. See
|
||||
Success ResponseStatus = 0
|
||||
Malformed ResponseStatus = 1
|
||||
InternalError ResponseStatus = 2
|
||||
TryLater ResponseStatus = 3
|
||||
// Status code four is unused in OCSP. See
|
||||
// https://tools.ietf.org/html/rfc6960#section-4.2.1
|
||||
SignatureRequired ResponseStatus = 5
|
||||
Unauthorized ResponseStatus = 6
|
||||
@@ -114,7 +114,7 @@ type basicResponse struct {
|
||||
|
||||
type responseData struct {
|
||||
Raw asn1.RawContent
|
||||
Version int `asn1:"optional,default:1,explicit,tag:0"`
|
||||
Version int `asn1:"optional,default:0,explicit,tag:0"`
|
||||
RawResponderName asn1.RawValue `asn1:"optional,explicit,tag:1"`
|
||||
KeyHash []byte `asn1:"optional,explicit,tag:2"`
|
||||
ProducedAt time.Time `asn1:"generalized"`
|
||||
|
||||
6
vendor/golang.org/x/crypto/openpgp/keys.go
сгенерированный
поставляемый
6
vendor/golang.org/x/crypto/openpgp/keys.go
сгенерированный
поставляемый
@@ -504,6 +504,12 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
|
||||
},
|
||||
}
|
||||
|
||||
// If the user passes in a DefaultHash via packet.Config,
|
||||
// set the PreferredHash for the SelfSignature.
|
||||
if config != nil && config.DefaultHash != 0 {
|
||||
e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)}
|
||||
}
|
||||
|
||||
e.Subkeys = make([]Subkey, 1)
|
||||
e.Subkeys[0] = Subkey{
|
||||
PublicKey: packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey),
|
||||
|
||||
34
vendor/golang.org/x/crypto/openpgp/keys_test.go
сгенерированный
поставляемый
34
vendor/golang.org/x/crypto/openpgp/keys_test.go
сгенерированный
поставляемый
@@ -2,6 +2,7 @@ package openpgp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -271,6 +272,39 @@ func TestIdVerification(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewEntityWithPreferredHash(t *testing.T) {
|
||||
c := &packet.Config{
|
||||
DefaultHash: crypto.SHA256,
|
||||
}
|
||||
entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, identity := range entity.Identities {
|
||||
if len(identity.SelfSignature.PreferredHash) == 0 {
|
||||
t.Fatal("didn't find a preferred hash in self signature")
|
||||
}
|
||||
ph := hashToHashId(c.DefaultHash)
|
||||
if identity.SelfSignature.PreferredHash[0] != ph {
|
||||
t.Fatalf("Expected preferred hash to be %d, got %d", ph, identity.SelfSignature.PreferredHash[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewEntityWithoutPreferredHash(t *testing.T) {
|
||||
entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, identity := range entity.Identities {
|
||||
if len(identity.SelfSignature.PreferredHash) != 0 {
|
||||
t.Fatal("Expected preferred hash to be empty but got length %d", len(identity.SelfSignature.PreferredHash))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const expiringKeyHex = "988d0451d1ec5d010400ba3385721f2dc3f4ab096b2ee867ab77213f0a27a8538441c35d2fa225b08798a1439a66a5150e6bdc3f40f5d28d588c712394c632b6299f77db8c0d48d37903fb72ebd794d61be6aa774688839e5fdecfe06b2684cc115d240c98c66cb1ef22ae84e3aa0c2b0c28665c1e7d4d044e7f270706193f5223c8d44e0d70b7b8da830011010001b40f4578706972792074657374206b657988be041301020028050251d1ec5d021b03050900278d00060b090807030206150802090a0b0416020301021e01021780000a091072589ad75e237d8c033503fd10506d72837834eb7f994117740723adc39227104b0d326a1161871c0b415d25b4aedef946ca77ea4c05af9c22b32cf98be86ab890111fced1ee3f75e87b7cc3c00dc63bbc85dfab91c0dc2ad9de2c4d13a34659333a85c6acc1a669c5e1d6cecb0cf1e56c10e72d855ae177ddc9e766f9b2dda57ccbb75f57156438bbdb4e42b88d0451d1ec5d0104009c64906559866c5cb61578f5846a94fcee142a489c9b41e67b12bb54cfe86eb9bc8566460f9a720cb00d6526fbccfd4f552071a8e3f7744b1882d01036d811ee5a3fb91a1c568055758f43ba5d2c6a9676b012f3a1a89e47bbf624f1ad571b208f3cc6224eb378f1645dd3d47584463f9eadeacfd1ce6f813064fbfdcc4b5a53001101000188a504180102000f021b0c050251d1f06b050900093e89000a091072589ad75e237d8c20e00400ab8310a41461425b37889c4da28129b5fae6084fafbc0a47dd1adc74a264c6e9c9cc125f40462ee1433072a58384daef88c961c390ed06426a81b464a53194c4e291ddd7e2e2ba3efced01537d713bd111f48437bde2363446200995e8e0d4e528dda377fd1e8f8ede9c8e2198b393bd86852ce7457a7e3daf74d510461a5b77b88d0451d1ece8010400b3a519f83ab0010307e83bca895170acce8964a044190a2b368892f7a244758d9fc193482648acb1fb9780d28cc22d171931f38bb40279389fc9bf2110876d4f3db4fcfb13f22f7083877fe56592b3b65251312c36f83ffcb6d313c6a17f197dd471f0712aad15a8537b435a92471ba2e5b0c72a6c72536c3b567c558d7b6051001101000188a504180102000f021b0c050251d1f07b050900279091000a091072589ad75e237d8ce69e03fe286026afacf7c97ee20673864d4459a2240b5655219950643c7dba0ac384b1d4359c67805b21d98211f7b09c2a0ccf6410c8c04d4ff4a51293725d8d6570d9d8bb0e10c07d22357caeb49626df99c180be02d77d1fe8ed25e7a54481237646083a9f89a11566cd20b9e995b1487c5f9e02aeb434f3a1897cd416dd0a87861838da3e9e"
|
||||
const subkeyUsageHex = "988d04533a52bc010400d26af43085558f65b9e7dbc90cb9238015259aed5e954637adcfa2181548b2d0b60c65f1f42ec5081cbf1bc0a8aa4900acfb77070837c58f26012fbce297d70afe96e759ad63531f0037538e70dbf8e384569b9720d99d8eb39d8d0a2947233ed242436cb6ac7dfe74123354b3d0119b5c235d3dd9c9d6c004f8ffaf67ad8583001101000188b7041f010200210502533b8552170c8001ce094aa433f7040bb2ddf0be3893cb843d0fe70c020700000a0910a42704b92866382aa98404009d63d916a27543da4221c60087c33f1c44bec9998c5438018ed370cca4962876c748e94b73eb39c58eb698063f3fd6346d58dd2a11c0247934c4a9d71f24754f7468f96fb24c3e791dd2392b62f626148ad724189498cbf993db2df7c0cdc2d677c35da0f16cb16c9ce7c33b4de65a4a91b1d21a130ae9cc26067718910ef8e2b417556d627261203c756d627261407379642e65642e61753e88b80413010200220502533a52bc021b03060b090807030206150802090a0b0416020301021e01021780000a0910a42704b92866382a47840400c0c2bd04f5fca586de408b395b3c280a278259c93eaaa8b79a53b97003f8ed502a8a00446dd9947fb462677e4fcac0dac2f0701847d15130aadb6cd9e0705ea0cf5f92f129136c7be21a718d46c8e641eb7f044f2adae573e11ae423a0a9ca51324f03a8a2f34b91fa40c3cc764bee4dccadedb54c768ba0469b683ea53f1c29b88d04533a52bc01040099c92a5d6f8b744224da27bc2369127c35269b58bec179de6bbc038f749344222f85a31933224f26b70243c4e4b2d242f0c4777eaef7b5502f9dad6d8bf3aaeb471210674b74de2d7078af497d55f5cdad97c7bedfbc1b41e8065a97c9c3d344b21fc81d27723af8e374bc595da26ea242dccb6ae497be26eea57e563ed517e90011010001889f0418010200090502533a52bc021b0c000a0910a42704b92866382afa1403ff70284c2de8a043ff51d8d29772602fa98009b7861c540535f874f2c230af8caf5638151a636b21f8255003997ccd29747fdd06777bb24f9593bd7d98a3e887689bf902f999915fcc94625ae487e5d13e6616f89090ebc4fdc7eb5cad8943e4056995bb61c6af37f8043016876a958ec7ebf39c43d20d53b7f546cfa83e8d2604b88d04533b8283010400c0b529316dbdf58b4c54461e7e669dc11c09eb7f73819f178ccd4177b9182b91d138605fcf1e463262fabefa73f94a52b5e15d1904635541c7ea540f07050ce0fb51b73e6f88644cec86e91107c957a114f69554548a85295d2b70bd0b203992f76eb5d493d86d9eabcaa7ef3fc7db7e458438db3fcdb0ca1cc97c638439a9170011010001889f0418010200090502533b8283021b0c000a0910a42704b92866382adc6d0400cfff6258485a21675adb7a811c3e19ebca18851533f75a7ba317950b9997fda8d1a4c8c76505c08c04b6c2cc31dc704d33da36a21273f2b388a1a706f7c3378b66d887197a525936ed9a69acb57fe7f718133da85ec742001c5d1864e9c6c8ea1b94f1c3759cebfd93b18606066c063a63be86085b7e37bdbc65f9a915bf084bb901a204533b85cd110400aed3d2c52af2b38b5b67904b0ef73d6dd7aef86adb770e2b153cd22489654dcc91730892087bb9856ae2d9f7ed1eb48f214243fe86bfe87b349ebd7c30e630e49c07b21fdabf78b7a95c8b7f969e97e3d33f2e074c63552ba64a2ded7badc05ce0ea2be6d53485f6900c7860c7aa76560376ce963d7271b9b54638a4028b573f00a0d8854bfcdb04986141568046202192263b9b67350400aaa1049dbc7943141ef590a70dcb028d730371d92ea4863de715f7f0f16d168bd3dc266c2450457d46dcbbf0b071547e5fbee7700a820c3750b236335d8d5848adb3c0da010e998908dfd93d961480084f3aea20b247034f8988eccb5546efaa35a92d0451df3aaf1aee5aa36a4c4d462c760ecd9cebcabfbe1412b1f21450f203fd126687cd486496e971a87fd9e1a8a765fe654baa219a6871ab97768596ab05c26c1aeea8f1a2c72395a58dbc12ef9640d2b95784e974a4d2d5a9b17c25fedacfe551bda52602de8f6d2e48443f5dd1a2a2a8e6a5e70ecdb88cd6e766ad9745c7ee91d78cc55c3d06536b49c3fee6c3d0b6ff0fb2bf13a314f57c953b8f4d93bf88e70418010200090502533b85cd021b0200520910a42704b92866382a47200419110200060502533b85cd000a091042ce2c64bc0ba99214b2009e26b26852c8b13b10c35768e40e78fbbb48bd084100a0c79d9ea0844fa5853dd3c85ff3ecae6f2c9dd6c557aa04008bbbc964cd65b9b8299d4ebf31f41cc7264b8cf33a00e82c5af022331fac79efc9563a822497ba012953cefe2629f1242fcdcb911dbb2315985bab060bfd58261ace3c654bdbbe2e8ed27a46e836490145c86dc7bae15c011f7e1ffc33730109b9338cd9f483e7cef3d2f396aab5bd80efb6646d7e778270ee99d934d187dd98"
|
||||
const revokedKeyHex = "988d045331ce82010400c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be10011010001889f04200102000905025331d0e3021d03000a0910a401d9f09a34f7c042aa040086631196405b7e6af71026b88e98012eab44aa9849f6ef3fa930c7c9f23deaedba9db1538830f8652fb7648ec3fcade8dbcbf9eaf428e83c6cbcc272201bfe2fbb90d41963397a7c0637a1a9d9448ce695d9790db2dc95433ad7be19eb3de72dacf1d6db82c3644c13eae2a3d072b99bb341debba012c5ce4006a7d34a1f4b94b444526567205265766f6b657220283c52656727732022424d204261726973746122204b657920262530305c303e5c29203c72656740626d626172697374612e636f2e61753e88b704130102002205025331ce82021b03060b090807030206150802090a0b0416020301021e01021780000a0910a401d9f09a34f7c0019c03f75edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56889c04100102000605025331cfb5000a0910fe9645554e8266b64b4303fc084075396674fb6f778d302ac07cef6bc0b5d07b66b2004c44aef711cbac79617ef06d836b4957522d8772dd94bf41a2f4ac8b1ee6d70c57503f837445a74765a076d07b829b8111fc2a918423ddb817ead7ca2a613ef0bfb9c6b3562aec6c3cf3c75ef3031d81d95f6563e4cdcc9960bcb386c5d757b104fcca5fe11fc709df884604101102000605025331cfe7000a09107b15a67f0b3ddc0317f6009e360beea58f29c1d963a22b962b80788c3fa6c84e009d148cfde6b351469b8eae91187eff07ad9d08fcaab88d045331ce820104009f25e20a42b904f3fa555530fe5c46737cf7bd076c35a2a0d22b11f7e0b61a69320b768f4a80fe13980ce380d1cfc4a0cd8fbe2d2e2ef85416668b77208baa65bf973fe8e500e78cc310d7c8705cdb34328bf80e24f0385fce5845c33bc7943cf6b11b02348a23da0bf6428e57c05135f2dc6bd7c1ce325d666d5a5fd2fd5e410011010001889f04180102000905025331ce82021b0c000a0910a401d9f09a34f7c0418003fe34feafcbeaef348a800a0d908a7a6809cc7304017d820f70f0474d5e23cb17e38b67dc6dca282c6ca00961f4ec9edf2738d0f087b1d81e4871ef08e1798010863afb4eac4c44a376cb343be929c5be66a78cfd4456ae9ec6a99d97f4e1c3ff3583351db2147a65c0acef5c003fb544ab3a2e2dc4d43646f58b811a6c3a369d1f"
|
||||
|
||||
2
vendor/golang.org/x/crypto/openpgp/packet/signature.go
сгенерированный
поставляемый
2
vendor/golang.org/x/crypto/openpgp/packet/signature.go
сгенерированный
поставляемый
@@ -553,7 +553,7 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
|
||||
func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error {
|
||||
h, err := userIdSignatureHash(id, pub, sig.Hash)
|
||||
if err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
return sig.Sign(h, priv, config)
|
||||
}
|
||||
|
||||
36
vendor/golang.org/x/crypto/openpgp/packet/signature_test.go
сгенерированный
поставляемый
36
vendor/golang.org/x/crypto/openpgp/packet/signature_test.go
сгенерированный
поставляемый
@@ -39,4 +39,40 @@ func TestSignatureReserialize(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSignUserId(t *testing.T) {
|
||||
sig := &Signature{
|
||||
SigType: SigTypeGenericCert,
|
||||
PubKeyAlgo: PubKeyAlgoRSA,
|
||||
Hash: 0, // invalid hash function
|
||||
}
|
||||
|
||||
packet, err := Read(readerFromHex(rsaPkDataHex))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to deserialize public key: %v", err)
|
||||
}
|
||||
pubKey := packet.(*PublicKey)
|
||||
|
||||
packet, err = Read(readerFromHex(privKeyRSAHex))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to deserialize private key: %v", err)
|
||||
}
|
||||
privKey := packet.(*PrivateKey)
|
||||
|
||||
err = sig.SignUserId("", pubKey, privKey, nil)
|
||||
if err == nil {
|
||||
t.Errorf("did not receive an error when expected")
|
||||
}
|
||||
|
||||
sig.Hash = crypto.SHA256
|
||||
err = privKey.Decrypt([]byte("testing"))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to decrypt private key: %v", err)
|
||||
}
|
||||
|
||||
err = sig.SignUserId("", pubKey, privKey, nil)
|
||||
if err != nil {
|
||||
t.Errorf("failed to sign user id: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
const signatureDataHex = "c2c05c04000102000605024cb45112000a0910ab105c91af38fb158f8d07ff5596ea368c5efe015bed6e78348c0f033c931d5f2ce5db54ce7f2a7e4b4ad64db758d65a7a71773edeab7ba2a9e0908e6a94a1175edd86c1d843279f045b021a6971a72702fcbd650efc393c5474d5b59a15f96d2eaad4c4c426797e0dcca2803ef41c6ff234d403eec38f31d610c344c06f2401c262f0993b2e66cad8a81ebc4322c723e0d4ba09fe917e8777658307ad8329adacba821420741009dfe87f007759f0982275d028a392c6ed983a0d846f890b36148c7358bdb8a516007fac760261ecd06076813831a36d0459075d1befa245ae7f7fb103d92ca759e9498fe60ef8078a39a3beda510deea251ea9f0a7f0df6ef42060f20780360686f3e400e"
|
||||
|
||||
2
vendor/golang.org/x/crypto/openpgp/write.go
сгенерированный
поставляемый
2
vendor/golang.org/x/crypto/openpgp/write.go
сгенерированный
поставляемый
@@ -231,7 +231,7 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
|
||||
}
|
||||
|
||||
cipher := packet.CipherFunction(candidateCiphers[0])
|
||||
// If the cipher specifed by config is a candidate, we'll use that.
|
||||
// If the cipher specified by config is a candidate, we'll use that.
|
||||
configuredCipher := config.Cipher()
|
||||
for _, c := range candidateCiphers {
|
||||
cipherFunc := packet.CipherFunction(c)
|
||||
|
||||
2
vendor/golang.org/x/crypto/scrypt/scrypt.go
сгенерированный
поставляемый
2
vendor/golang.org/x/crypto/scrypt/scrypt.go
сгенерированный
поставляемый
@@ -218,7 +218,7 @@ func smix(b []byte, r, N int, v, xy []uint32) {
|
||||
// For example, you can get a derived key for e.g. AES-256 (which needs a
|
||||
// 32-byte key) by doing:
|
||||
//
|
||||
// dk := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32)
|
||||
// dk, err := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32)
|
||||
//
|
||||
// The recommended parameters for interactive logins as of 2009 are N=16384,
|
||||
// r=8, p=1. They should be increased as memory latency and CPU parallelism
|
||||
|
||||
2
vendor/golang.org/x/crypto/sha3/keccakf.go
сгенерированный
поставляемый
2
vendor/golang.org/x/crypto/sha3/keccakf.go
сгенерированный
поставляемый
@@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !amd64 appengine gccgo
|
||||
|
||||
package sha3
|
||||
|
||||
// rc stores the round constants for use in the ι step.
|
||||
|
||||
13
vendor/golang.org/x/crypto/sha3/keccakf_amd64.go
сгенерированный
поставляемый
Обычный файл
13
vendor/golang.org/x/crypto/sha3/keccakf_amd64.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,13 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// +build amd64,!appengine,!gccgo
|
||||
|
||||
package sha3
|
||||
|
||||
// This function is implemented in keccakf_amd64.s.
|
||||
|
||||
//go:noescape
|
||||
|
||||
func keccakF1600(a *[25]uint64)
|
||||
392
vendor/golang.org/x/crypto/sha3/keccakf_amd64.s
сгенерированный
поставляемый
Обычный файл
392
vendor/golang.org/x/crypto/sha3/keccakf_amd64.s
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,392 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// +build amd64,!appengine,!gccgo
|
||||
|
||||
// This code was translated into a form compatible with 6a from the public
|
||||
// domain sources at https://github.com/gvanas/KeccakCodePackage
|
||||
|
||||
// Offsets in state
|
||||
#define _ba (0*8)
|
||||
#define _be (1*8)
|
||||
#define _bi (2*8)
|
||||
#define _bo (3*8)
|
||||
#define _bu (4*8)
|
||||
#define _ga (5*8)
|
||||
#define _ge (6*8)
|
||||
#define _gi (7*8)
|
||||
#define _go (8*8)
|
||||
#define _gu (9*8)
|
||||
#define _ka (10*8)
|
||||
#define _ke (11*8)
|
||||
#define _ki (12*8)
|
||||
#define _ko (13*8)
|
||||
#define _ku (14*8)
|
||||
#define _ma (15*8)
|
||||
#define _me (16*8)
|
||||
#define _mi (17*8)
|
||||
#define _mo (18*8)
|
||||
#define _mu (19*8)
|
||||
#define _sa (20*8)
|
||||
#define _se (21*8)
|
||||
#define _si (22*8)
|
||||
#define _so (23*8)
|
||||
#define _su (24*8)
|
||||
|
||||
// Temporary registers
|
||||
#define rT1 AX
|
||||
|
||||
// Round vars
|
||||
#define rpState DI
|
||||
#define rpStack SP
|
||||
|
||||
#define rDa BX
|
||||
#define rDe CX
|
||||
#define rDi DX
|
||||
#define rDo R8
|
||||
#define rDu R9
|
||||
|
||||
#define rBa R10
|
||||
#define rBe R11
|
||||
#define rBi R12
|
||||
#define rBo R13
|
||||
#define rBu R14
|
||||
|
||||
#define rCa SI
|
||||
#define rCe BP
|
||||
#define rCi rBi
|
||||
#define rCo rBo
|
||||
#define rCu R15
|
||||
|
||||
#define MOVQ_RBI_RCE MOVQ rBi, rCe
|
||||
#define XORQ_RT1_RCA XORQ rT1, rCa
|
||||
#define XORQ_RT1_RCE XORQ rT1, rCe
|
||||
#define XORQ_RBA_RCU XORQ rBa, rCu
|
||||
#define XORQ_RBE_RCU XORQ rBe, rCu
|
||||
#define XORQ_RDU_RCU XORQ rDu, rCu
|
||||
#define XORQ_RDA_RCA XORQ rDa, rCa
|
||||
#define XORQ_RDE_RCE XORQ rDe, rCe
|
||||
|
||||
#define mKeccakRound(iState, oState, rc, B_RBI_RCE, G_RT1_RCA, G_RT1_RCE, G_RBA_RCU, K_RT1_RCA, K_RT1_RCE, K_RBA_RCU, M_RT1_RCA, M_RT1_RCE, M_RBE_RCU, S_RDU_RCU, S_RDA_RCA, S_RDE_RCE) \
|
||||
/* Prepare round */ \
|
||||
MOVQ rCe, rDa; \
|
||||
ROLQ $1, rDa; \
|
||||
\
|
||||
MOVQ _bi(iState), rCi; \
|
||||
XORQ _gi(iState), rDi; \
|
||||
XORQ rCu, rDa; \
|
||||
XORQ _ki(iState), rCi; \
|
||||
XORQ _mi(iState), rDi; \
|
||||
XORQ rDi, rCi; \
|
||||
\
|
||||
MOVQ rCi, rDe; \
|
||||
ROLQ $1, rDe; \
|
||||
\
|
||||
MOVQ _bo(iState), rCo; \
|
||||
XORQ _go(iState), rDo; \
|
||||
XORQ rCa, rDe; \
|
||||
XORQ _ko(iState), rCo; \
|
||||
XORQ _mo(iState), rDo; \
|
||||
XORQ rDo, rCo; \
|
||||
\
|
||||
MOVQ rCo, rDi; \
|
||||
ROLQ $1, rDi; \
|
||||
\
|
||||
MOVQ rCu, rDo; \
|
||||
XORQ rCe, rDi; \
|
||||
ROLQ $1, rDo; \
|
||||
\
|
||||
MOVQ rCa, rDu; \
|
||||
XORQ rCi, rDo; \
|
||||
ROLQ $1, rDu; \
|
||||
\
|
||||
/* Result b */ \
|
||||
MOVQ _ba(iState), rBa; \
|
||||
MOVQ _ge(iState), rBe; \
|
||||
XORQ rCo, rDu; \
|
||||
MOVQ _ki(iState), rBi; \
|
||||
MOVQ _mo(iState), rBo; \
|
||||
MOVQ _su(iState), rBu; \
|
||||
XORQ rDe, rBe; \
|
||||
ROLQ $44, rBe; \
|
||||
XORQ rDi, rBi; \
|
||||
XORQ rDa, rBa; \
|
||||
ROLQ $43, rBi; \
|
||||
\
|
||||
MOVQ rBe, rCa; \
|
||||
MOVQ rc, rT1; \
|
||||
ORQ rBi, rCa; \
|
||||
XORQ rBa, rT1; \
|
||||
XORQ rT1, rCa; \
|
||||
MOVQ rCa, _ba(oState); \
|
||||
\
|
||||
XORQ rDu, rBu; \
|
||||
ROLQ $14, rBu; \
|
||||
MOVQ rBa, rCu; \
|
||||
ANDQ rBe, rCu; \
|
||||
XORQ rBu, rCu; \
|
||||
MOVQ rCu, _bu(oState); \
|
||||
\
|
||||
XORQ rDo, rBo; \
|
||||
ROLQ $21, rBo; \
|
||||
MOVQ rBo, rT1; \
|
||||
ANDQ rBu, rT1; \
|
||||
XORQ rBi, rT1; \
|
||||
MOVQ rT1, _bi(oState); \
|
||||
\
|
||||
NOTQ rBi; \
|
||||
ORQ rBa, rBu; \
|
||||
ORQ rBo, rBi; \
|
||||
XORQ rBo, rBu; \
|
||||
XORQ rBe, rBi; \
|
||||
MOVQ rBu, _bo(oState); \
|
||||
MOVQ rBi, _be(oState); \
|
||||
B_RBI_RCE; \
|
||||
\
|
||||
/* Result g */ \
|
||||
MOVQ _gu(iState), rBe; \
|
||||
XORQ rDu, rBe; \
|
||||
MOVQ _ka(iState), rBi; \
|
||||
ROLQ $20, rBe; \
|
||||
XORQ rDa, rBi; \
|
||||
ROLQ $3, rBi; \
|
||||
MOVQ _bo(iState), rBa; \
|
||||
MOVQ rBe, rT1; \
|
||||
ORQ rBi, rT1; \
|
||||
XORQ rDo, rBa; \
|
||||
MOVQ _me(iState), rBo; \
|
||||
MOVQ _si(iState), rBu; \
|
||||
ROLQ $28, rBa; \
|
||||
XORQ rBa, rT1; \
|
||||
MOVQ rT1, _ga(oState); \
|
||||
G_RT1_RCA; \
|
||||
\
|
||||
XORQ rDe, rBo; \
|
||||
ROLQ $45, rBo; \
|
||||
MOVQ rBi, rT1; \
|
||||
ANDQ rBo, rT1; \
|
||||
XORQ rBe, rT1; \
|
||||
MOVQ rT1, _ge(oState); \
|
||||
G_RT1_RCE; \
|
||||
\
|
||||
XORQ rDi, rBu; \
|
||||
ROLQ $61, rBu; \
|
||||
MOVQ rBu, rT1; \
|
||||
ORQ rBa, rT1; \
|
||||
XORQ rBo, rT1; \
|
||||
MOVQ rT1, _go(oState); \
|
||||
\
|
||||
ANDQ rBe, rBa; \
|
||||
XORQ rBu, rBa; \
|
||||
MOVQ rBa, _gu(oState); \
|
||||
NOTQ rBu; \
|
||||
G_RBA_RCU; \
|
||||
\
|
||||
ORQ rBu, rBo; \
|
||||
XORQ rBi, rBo; \
|
||||
MOVQ rBo, _gi(oState); \
|
||||
\
|
||||
/* Result k */ \
|
||||
MOVQ _be(iState), rBa; \
|
||||
MOVQ _gi(iState), rBe; \
|
||||
MOVQ _ko(iState), rBi; \
|
||||
MOVQ _mu(iState), rBo; \
|
||||
MOVQ _sa(iState), rBu; \
|
||||
XORQ rDi, rBe; \
|
||||
ROLQ $6, rBe; \
|
||||
XORQ rDo, rBi; \
|
||||
ROLQ $25, rBi; \
|
||||
MOVQ rBe, rT1; \
|
||||
ORQ rBi, rT1; \
|
||||
XORQ rDe, rBa; \
|
||||
ROLQ $1, rBa; \
|
||||
XORQ rBa, rT1; \
|
||||
MOVQ rT1, _ka(oState); \
|
||||
K_RT1_RCA; \
|
||||
\
|
||||
XORQ rDu, rBo; \
|
||||
ROLQ $8, rBo; \
|
||||
MOVQ rBi, rT1; \
|
||||
ANDQ rBo, rT1; \
|
||||
XORQ rBe, rT1; \
|
||||
MOVQ rT1, _ke(oState); \
|
||||
K_RT1_RCE; \
|
||||
\
|
||||
XORQ rDa, rBu; \
|
||||
ROLQ $18, rBu; \
|
||||
NOTQ rBo; \
|
||||
MOVQ rBo, rT1; \
|
||||
ANDQ rBu, rT1; \
|
||||
XORQ rBi, rT1; \
|
||||
MOVQ rT1, _ki(oState); \
|
||||
\
|
||||
MOVQ rBu, rT1; \
|
||||
ORQ rBa, rT1; \
|
||||
XORQ rBo, rT1; \
|
||||
MOVQ rT1, _ko(oState); \
|
||||
\
|
||||
ANDQ rBe, rBa; \
|
||||
XORQ rBu, rBa; \
|
||||
MOVQ rBa, _ku(oState); \
|
||||
K_RBA_RCU; \
|
||||
\
|
||||
/* Result m */ \
|
||||
MOVQ _ga(iState), rBe; \
|
||||
XORQ rDa, rBe; \
|
||||
MOVQ _ke(iState), rBi; \
|
||||
ROLQ $36, rBe; \
|
||||
XORQ rDe, rBi; \
|
||||
MOVQ _bu(iState), rBa; \
|
||||
ROLQ $10, rBi; \
|
||||
MOVQ rBe, rT1; \
|
||||
MOVQ _mi(iState), rBo; \
|
||||
ANDQ rBi, rT1; \
|
||||
XORQ rDu, rBa; \
|
||||
MOVQ _so(iState), rBu; \
|
||||
ROLQ $27, rBa; \
|
||||
XORQ rBa, rT1; \
|
||||
MOVQ rT1, _ma(oState); \
|
||||
M_RT1_RCA; \
|
||||
\
|
||||
XORQ rDi, rBo; \
|
||||
ROLQ $15, rBo; \
|
||||
MOVQ rBi, rT1; \
|
||||
ORQ rBo, rT1; \
|
||||
XORQ rBe, rT1; \
|
||||
MOVQ rT1, _me(oState); \
|
||||
M_RT1_RCE; \
|
||||
\
|
||||
XORQ rDo, rBu; \
|
||||
ROLQ $56, rBu; \
|
||||
NOTQ rBo; \
|
||||
MOVQ rBo, rT1; \
|
||||
ORQ rBu, rT1; \
|
||||
XORQ rBi, rT1; \
|
||||
MOVQ rT1, _mi(oState); \
|
||||
\
|
||||
ORQ rBa, rBe; \
|
||||
XORQ rBu, rBe; \
|
||||
MOVQ rBe, _mu(oState); \
|
||||
\
|
||||
ANDQ rBa, rBu; \
|
||||
XORQ rBo, rBu; \
|
||||
MOVQ rBu, _mo(oState); \
|
||||
M_RBE_RCU; \
|
||||
\
|
||||
/* Result s */ \
|
||||
MOVQ _bi(iState), rBa; \
|
||||
MOVQ _go(iState), rBe; \
|
||||
MOVQ _ku(iState), rBi; \
|
||||
XORQ rDi, rBa; \
|
||||
MOVQ _ma(iState), rBo; \
|
||||
ROLQ $62, rBa; \
|
||||
XORQ rDo, rBe; \
|
||||
MOVQ _se(iState), rBu; \
|
||||
ROLQ $55, rBe; \
|
||||
\
|
||||
XORQ rDu, rBi; \
|
||||
MOVQ rBa, rDu; \
|
||||
XORQ rDe, rBu; \
|
||||
ROLQ $2, rBu; \
|
||||
ANDQ rBe, rDu; \
|
||||
XORQ rBu, rDu; \
|
||||
MOVQ rDu, _su(oState); \
|
||||
\
|
||||
ROLQ $39, rBi; \
|
||||
S_RDU_RCU; \
|
||||
NOTQ rBe; \
|
||||
XORQ rDa, rBo; \
|
||||
MOVQ rBe, rDa; \
|
||||
ANDQ rBi, rDa; \
|
||||
XORQ rBa, rDa; \
|
||||
MOVQ rDa, _sa(oState); \
|
||||
S_RDA_RCA; \
|
||||
\
|
||||
ROLQ $41, rBo; \
|
||||
MOVQ rBi, rDe; \
|
||||
ORQ rBo, rDe; \
|
||||
XORQ rBe, rDe; \
|
||||
MOVQ rDe, _se(oState); \
|
||||
S_RDE_RCE; \
|
||||
\
|
||||
MOVQ rBo, rDi; \
|
||||
MOVQ rBu, rDo; \
|
||||
ANDQ rBu, rDi; \
|
||||
ORQ rBa, rDo; \
|
||||
XORQ rBi, rDi; \
|
||||
XORQ rBo, rDo; \
|
||||
MOVQ rDi, _si(oState); \
|
||||
MOVQ rDo, _so(oState) \
|
||||
|
||||
// func keccakF1600(state *[25]uint64)
|
||||
TEXT ·keccakF1600(SB), 0, $200-8
|
||||
MOVQ state+0(FP), rpState
|
||||
SUBQ $(8*25), SP
|
||||
|
||||
// Convert the user state into an internal state
|
||||
NOTQ _be(rpState)
|
||||
NOTQ _bi(rpState)
|
||||
NOTQ _go(rpState)
|
||||
NOTQ _ki(rpState)
|
||||
NOTQ _mi(rpState)
|
||||
NOTQ _sa(rpState)
|
||||
|
||||
// Execute the KeccakF permutation
|
||||
MOVQ _ba(rpState), rCa
|
||||
MOVQ _be(rpState), rCe
|
||||
MOVQ _bu(rpState), rCu
|
||||
|
||||
XORQ _ga(rpState), rCa
|
||||
XORQ _ge(rpState), rCe
|
||||
XORQ _gu(rpState), rCu
|
||||
|
||||
XORQ _ka(rpState), rCa
|
||||
XORQ _ke(rpState), rCe
|
||||
XORQ _ku(rpState), rCu
|
||||
|
||||
XORQ _ma(rpState), rCa
|
||||
XORQ _me(rpState), rCe
|
||||
XORQ _mu(rpState), rCu
|
||||
|
||||
XORQ _sa(rpState), rCa
|
||||
XORQ _se(rpState), rCe
|
||||
MOVQ _si(rpState), rDi
|
||||
MOVQ _so(rpState), rDo
|
||||
XORQ _su(rpState), rCu
|
||||
|
||||
mKeccakRound(rpState, rpStack, $0x0000000000000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpStack, rpState, $0x0000000000008082, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpState, rpStack, $0x800000000000808a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpStack, rpState, $0x8000000080008000, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpState, rpStack, $0x000000000000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpStack, rpState, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpStack, rpState, $0x8000000000008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpState, rpStack, $0x000000000000008a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpStack, rpState, $0x0000000000000088, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpState, rpStack, $0x0000000080008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpStack, rpState, $0x000000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpState, rpStack, $0x000000008000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpStack, rpState, $0x800000000000008b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpState, rpStack, $0x8000000000008089, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpStack, rpState, $0x8000000000008003, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpState, rpStack, $0x8000000000008002, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpStack, rpState, $0x8000000000000080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpState, rpStack, $0x000000000000800a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpStack, rpState, $0x800000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpStack, rpState, $0x8000000000008080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpState, rpStack, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
|
||||
mKeccakRound(rpStack, rpState, $0x8000000080008008, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP)
|
||||
|
||||
// Revert the internal state to the user state
|
||||
NOTQ _be(rpState)
|
||||
NOTQ _bi(rpState)
|
||||
NOTQ _go(rpState)
|
||||
NOTQ _ki(rpState)
|
||||
NOTQ _mi(rpState)
|
||||
NOTQ _sa(rpState)
|
||||
|
||||
ADDQ $(8*25), SP
|
||||
RET
|
||||
2
vendor/golang.org/x/crypto/sha3/sha3.go
сгенерированный
поставляемый
2
vendor/golang.org/x/crypto/sha3/sha3.go
сгенерированный
поставляемый
@@ -42,7 +42,7 @@ type state struct {
|
||||
storage [maxRate]byte
|
||||
|
||||
// Specific to SHA-3 and SHAKE.
|
||||
fixedOutput bool // whether this is a fixed-ouput-length instance
|
||||
fixedOutput bool // whether this is a fixed-output-length instance
|
||||
outputLen int // the default output size in bytes
|
||||
state spongeDirection // whether the sponge is absorbing or squeezing
|
||||
}
|
||||
|
||||
55
vendor/golang.org/x/crypto/ssh/agent/client.go
сгенерированный
поставляемый
55
vendor/golang.org/x/crypto/ssh/agent/client.go
сгенерированный
поставляемый
@@ -25,6 +25,7 @@ import (
|
||||
"math/big"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
@@ -423,6 +424,14 @@ type ecdsaKeyMsg struct {
|
||||
Constraints []byte `ssh:"rest"`
|
||||
}
|
||||
|
||||
type ed25519KeyMsg struct {
|
||||
Type string `sshtype:"17|25"`
|
||||
Pub []byte
|
||||
Priv []byte
|
||||
Comments string
|
||||
Constraints []byte `ssh:"rest"`
|
||||
}
|
||||
|
||||
// Insert adds a private key to the agent.
|
||||
func (c *client) insertKey(s interface{}, comment string, constraints []byte) error {
|
||||
var req []byte
|
||||
@@ -464,6 +473,14 @@ func (c *client) insertKey(s interface{}, comment string, constraints []byte) er
|
||||
Comments: comment,
|
||||
Constraints: constraints,
|
||||
})
|
||||
case *ed25519.PrivateKey:
|
||||
req = ssh.Marshal(ed25519KeyMsg{
|
||||
Type: ssh.KeyAlgoED25519,
|
||||
Pub: []byte(*k)[32:],
|
||||
Priv: []byte(*k),
|
||||
Comments: comment,
|
||||
Constraints: constraints,
|
||||
})
|
||||
default:
|
||||
return fmt.Errorf("agent: unsupported key type %T", s)
|
||||
}
|
||||
@@ -510,7 +527,16 @@ type ecdsaCertMsg struct {
|
||||
Constraints []byte `ssh:"rest"`
|
||||
}
|
||||
|
||||
// Insert adds a private key to the agent. If a certificate is given,
|
||||
type ed25519CertMsg struct {
|
||||
Type string `sshtype:"17|25"`
|
||||
CertBytes []byte
|
||||
Pub []byte
|
||||
Priv []byte
|
||||
Comments string
|
||||
Constraints []byte `ssh:"rest"`
|
||||
}
|
||||
|
||||
// Add adds a private key to the agent. If a certificate is given,
|
||||
// that certificate is added instead as public key.
|
||||
func (c *client) Add(key AddedKey) error {
|
||||
var constraints []byte
|
||||
@@ -554,17 +580,28 @@ func (c *client) insertCert(s interface{}, cert *ssh.Certificate, comment string
|
||||
})
|
||||
case *dsa.PrivateKey:
|
||||
req = ssh.Marshal(dsaCertMsg{
|
||||
Type: cert.Type(),
|
||||
CertBytes: cert.Marshal(),
|
||||
X: k.X,
|
||||
Comments: comment,
|
||||
Type: cert.Type(),
|
||||
CertBytes: cert.Marshal(),
|
||||
X: k.X,
|
||||
Comments: comment,
|
||||
Constraints: constraints,
|
||||
})
|
||||
case *ecdsa.PrivateKey:
|
||||
req = ssh.Marshal(ecdsaCertMsg{
|
||||
Type: cert.Type(),
|
||||
CertBytes: cert.Marshal(),
|
||||
D: k.D,
|
||||
Comments: comment,
|
||||
Type: cert.Type(),
|
||||
CertBytes: cert.Marshal(),
|
||||
D: k.D,
|
||||
Comments: comment,
|
||||
Constraints: constraints,
|
||||
})
|
||||
case *ed25519.PrivateKey:
|
||||
req = ssh.Marshal(ed25519CertMsg{
|
||||
Type: cert.Type(),
|
||||
CertBytes: cert.Marshal(),
|
||||
Pub: []byte(*k)[32:],
|
||||
Priv: []byte(*k),
|
||||
Comments: comment,
|
||||
Constraints: constraints,
|
||||
})
|
||||
default:
|
||||
return fmt.Errorf("agent: unsupported key type %T", s)
|
||||
|
||||
42
vendor/golang.org/x/crypto/ssh/agent/client_test.go
сгенерированный
поставляемый
42
vendor/golang.org/x/crypto/ssh/agent/client_test.go
сгенерированный
поставляемый
@@ -14,6 +14,7 @@ import (
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
@@ -139,7 +140,7 @@ func testAgentInterface(t *testing.T, agent Agent, key interface{}, cert *ssh.Ce
|
||||
}
|
||||
|
||||
func TestAgent(t *testing.T) {
|
||||
for _, keyType := range []string{"rsa", "dsa", "ecdsa"} {
|
||||
for _, keyType := range []string{"rsa", "dsa", "ecdsa", "ed25519"} {
|
||||
testAgent(t, testPrivateKeys[keyType], nil, 0)
|
||||
}
|
||||
}
|
||||
@@ -285,3 +286,42 @@ func testLockAgent(agent Agent, t *testing.T) {
|
||||
t.Errorf("Want 1 keys, got %v", keys)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgentLifetime(t *testing.T) {
|
||||
agent, _, cleanup := startAgent(t)
|
||||
defer cleanup()
|
||||
|
||||
for _, keyType := range []string{"rsa", "dsa", "ecdsa"} {
|
||||
// Add private keys to the agent.
|
||||
err := agent.Add(AddedKey{
|
||||
PrivateKey: testPrivateKeys[keyType],
|
||||
Comment: "comment",
|
||||
LifetimeSecs: 1,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("add: %v", err)
|
||||
}
|
||||
// Add certs to the agent.
|
||||
cert := &ssh.Certificate{
|
||||
Key: testPublicKeys[keyType],
|
||||
ValidBefore: ssh.CertTimeInfinity,
|
||||
CertType: ssh.UserCert,
|
||||
}
|
||||
cert.SignCert(rand.Reader, testSigners[keyType])
|
||||
err = agent.Add(AddedKey{
|
||||
PrivateKey: testPrivateKeys[keyType],
|
||||
Certificate: cert,
|
||||
Comment: "comment",
|
||||
LifetimeSecs: 1,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("add: %v", err)
|
||||
}
|
||||
}
|
||||
time.Sleep(1100 * time.Millisecond)
|
||||
if keys, err := agent.List(); err != nil {
|
||||
t.Errorf("List: %v", err)
|
||||
} else if len(keys) != 0 {
|
||||
t.Errorf("Want 0 keys, got %v", len(keys))
|
||||
}
|
||||
}
|
||||
|
||||
35
vendor/golang.org/x/crypto/ssh/agent/server.go
сгенерированный
поставляемый
35
vendor/golang.org/x/crypto/ssh/agent/server.go
сгенерированный
поставляемый
@@ -16,6 +16,7 @@ import (
|
||||
"log"
|
||||
"math/big"
|
||||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
@@ -175,6 +176,15 @@ func parseRSAKey(req []byte) (*AddedKey, error) {
|
||||
return &AddedKey{PrivateKey: priv, Comment: k.Comments}, nil
|
||||
}
|
||||
|
||||
func parseEd25519Key(req []byte) (*AddedKey, error) {
|
||||
var k ed25519KeyMsg
|
||||
if err := ssh.Unmarshal(req, &k); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
priv := ed25519.PrivateKey(k.Priv)
|
||||
return &AddedKey{PrivateKey: &priv, Comment: k.Comments}, nil
|
||||
}
|
||||
|
||||
func parseDSAKey(req []byte) (*AddedKey, error) {
|
||||
var k dsaKeyMsg
|
||||
if err := ssh.Unmarshal(req, &k); err != nil {
|
||||
@@ -219,6 +229,23 @@ func unmarshalECDSA(curveName string, keyBytes []byte, privScalar *big.Int) (pri
|
||||
return priv, nil
|
||||
}
|
||||
|
||||
func parseEd25519Cert(req []byte) (*AddedKey, error) {
|
||||
var k ed25519CertMsg
|
||||
if err := ssh.Unmarshal(req, &k); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pubKey, err := ssh.ParsePublicKey(k.CertBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
priv := ed25519.PrivateKey(k.Priv)
|
||||
cert, ok := pubKey.(*ssh.Certificate)
|
||||
if !ok {
|
||||
return nil, errors.New("agent: bad ED25519 certificate")
|
||||
}
|
||||
return &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}, nil
|
||||
}
|
||||
|
||||
func parseECDSAKey(req []byte) (*AddedKey, error) {
|
||||
var k ecdsaKeyMsg
|
||||
if err := ssh.Unmarshal(req, &k); err != nil {
|
||||
@@ -230,7 +257,7 @@ func parseECDSAKey(req []byte) (*AddedKey, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &AddedKey{PrivateKey: &priv, Comment: k.Comments}, nil
|
||||
return &AddedKey{PrivateKey: priv, Comment: k.Comments}, nil
|
||||
}
|
||||
|
||||
func parseRSACert(req []byte) (*AddedKey, error) {
|
||||
@@ -366,13 +393,17 @@ func (s *server) insertIdentity(req []byte) error {
|
||||
case ssh.KeyAlgoDSA:
|
||||
addedKey, err = parseDSAKey(req)
|
||||
case ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521:
|
||||
addedKey, err = parseECDSACert(req)
|
||||
addedKey, err = parseECDSAKey(req)
|
||||
case ssh.KeyAlgoED25519:
|
||||
addedKey, err = parseEd25519Key(req)
|
||||
case ssh.CertAlgoRSAv01:
|
||||
addedKey, err = parseRSACert(req)
|
||||
case ssh.CertAlgoDSAv01:
|
||||
addedKey, err = parseDSACert(req)
|
||||
case ssh.CertAlgoECDSA256v01, ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01:
|
||||
addedKey, err = parseECDSACert(req)
|
||||
case ssh.CertAlgoED25519v01:
|
||||
addedKey, err = parseEd25519Cert(req)
|
||||
default:
|
||||
return fmt.Errorf("agent: not implemented: %q", record.Type)
|
||||
}
|
||||
|
||||
21
vendor/golang.org/x/crypto/ssh/agent/server_test.go
сгенерированный
поставляемый
21
vendor/golang.org/x/crypto/ssh/agent/server_test.go
сгенерированный
поставляемый
@@ -150,9 +150,27 @@ func TestKeyTypes(t *testing.T) {
|
||||
if err := addKeyToAgent(v); err != nil {
|
||||
t.Errorf("error adding key type %s, %v", k, err)
|
||||
}
|
||||
if err := addCertToAgentSock(v, nil); err != nil {
|
||||
t.Errorf("error adding key type %s, %v", k, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addCertToAgentSock(key crypto.PrivateKey, cert *ssh.Certificate) error {
|
||||
a, b, err := netPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
agentServer := NewKeyring()
|
||||
go ServeAgent(agentServer, a)
|
||||
|
||||
agentClient := NewClient(b)
|
||||
if err := agentClient.Add(AddedKey{PrivateKey: key, Certificate: cert}); err != nil {
|
||||
return fmt.Errorf("add: %v", err)
|
||||
}
|
||||
return verifyKey(agentClient)
|
||||
}
|
||||
|
||||
func addCertToAgent(key crypto.PrivateKey, cert *ssh.Certificate) error {
|
||||
sshAgent := NewKeyring()
|
||||
if err := sshAgent.Add(AddedKey{PrivateKey: key, Certificate: cert}); err != nil {
|
||||
@@ -182,5 +200,8 @@ func TestCertTypes(t *testing.T) {
|
||||
if err := addCertToAgent(testPrivateKeys[keyType], cert); err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
if err := addCertToAgentSock(testPrivateKeys[keyType], cert); err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2
vendor/golang.org/x/crypto/ssh/agent/testdata_test.go
сгенерированный
поставляемый
2
vendor/golang.org/x/crypto/ssh/agent/testdata_test.go
сгенерированный
поставляемый
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// IMPLEMENTOR NOTE: To avoid a package loop, this file is in three places:
|
||||
// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places:
|
||||
// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three
|
||||
// instances.
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/ssh/channel.go
сгенерированный
поставляемый
2
vendor/golang.org/x/crypto/ssh/channel.go
сгенерированный
поставляемый
@@ -67,6 +67,8 @@ type Channel interface {
|
||||
// boolean, otherwise the return value will be false. Channel
|
||||
// requests are out-of-band messages so they may be sent even
|
||||
// if the data stream is closed or blocked by flow control.
|
||||
// If the channel is closed before a reply is returned, io.EOF
|
||||
// is returned.
|
||||
SendRequest(name string, wantReply bool, payload []byte) (bool, error)
|
||||
|
||||
// Stderr returns an io.ReadWriter that writes to this channel
|
||||
|
||||
39
vendor/golang.org/x/crypto/ssh/cipher.go
сгенерированный
поставляемый
39
vendor/golang.org/x/crypto/ssh/cipher.go
сгенерированный
поставляемый
@@ -7,6 +7,7 @@ package ssh
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/des"
|
||||
"crypto/rc4"
|
||||
"crypto/subtle"
|
||||
"encoding/binary"
|
||||
@@ -121,6 +122,9 @@ var cipherModes = map[string]*streamCipherMode{
|
||||
// You should expect that an active attacker can recover plaintext if
|
||||
// you do.
|
||||
aes128cbcID: {16, aes.BlockSize, 0, nil},
|
||||
|
||||
// 3des-cbc is insecure and is disabled by default.
|
||||
tripledescbcID: {24, des.BlockSize, 0, nil},
|
||||
}
|
||||
|
||||
// prefixLen is the length of the packet prefix that contains the packet length
|
||||
@@ -368,12 +372,7 @@ type cbcCipher struct {
|
||||
oracleCamouflage uint32
|
||||
}
|
||||
|
||||
func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
|
||||
c, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func newCBCCipher(c cipher.Block, iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
|
||||
cbc := &cbcCipher{
|
||||
mac: macModes[algs.MAC].new(macKey),
|
||||
decrypter: cipher.NewCBCDecrypter(c, iv),
|
||||
@@ -387,6 +386,34 @@ func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCi
|
||||
return cbc, nil
|
||||
}
|
||||
|
||||
func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
|
||||
c, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cbc, err := newCBCCipher(c, iv, key, macKey, algs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cbc, nil
|
||||
}
|
||||
|
||||
func newTripleDESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
|
||||
c, err := des.NewTripleDESCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cbc, err := newCBCCipher(c, iv, key, macKey, algs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cbc, nil
|
||||
}
|
||||
|
||||
func maxUInt32(a, b int) uint32 {
|
||||
if a > b {
|
||||
return uint32(a)
|
||||
|
||||
2
vendor/golang.org/x/crypto/ssh/cipher_test.go
сгенерированный
поставляемый
2
vendor/golang.org/x/crypto/ssh/cipher_test.go
сгенерированный
поставляемый
@@ -21,7 +21,7 @@ func TestDefaultCiphersExist(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPacketCiphers(t *testing.T) {
|
||||
// Still test aes128cbc cipher althought it's commented out.
|
||||
// Still test aes128cbc cipher although it's commented out.
|
||||
cipherModes[aes128cbcID] = &streamCipherMode{16, aes.BlockSize, 0, nil}
|
||||
defer delete(cipherModes, aes128cbcID)
|
||||
|
||||
|
||||
34
vendor/golang.org/x/crypto/ssh/client_auth.go
сгенерированный
поставляемый
34
vendor/golang.org/x/crypto/ssh/client_auth.go
сгенерированный
поставляемый
@@ -437,3 +437,37 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type retryableAuthMethod struct {
|
||||
authMethod AuthMethod
|
||||
maxTries int
|
||||
}
|
||||
|
||||
func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok bool, methods []string, err error) {
|
||||
for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ {
|
||||
ok, methods, err = r.authMethod.auth(session, user, c, rand)
|
||||
if ok || err != nil { // either success or error terminate
|
||||
return ok, methods, err
|
||||
}
|
||||
}
|
||||
return ok, methods, err
|
||||
}
|
||||
|
||||
func (r *retryableAuthMethod) method() string {
|
||||
return r.authMethod.method()
|
||||
}
|
||||
|
||||
// RetryableAuthMethod is a decorator for other auth methods enabling them to
|
||||
// be retried up to maxTries before considering that AuthMethod itself failed.
|
||||
// If maxTries is <= 0, will retry indefinitely
|
||||
//
|
||||
// This is useful for interactive clients using challenge/response type
|
||||
// authentication (e.g. Keyboard-Interactive, Password, etc) where the user
|
||||
// could mistype their response resulting in the server issuing a
|
||||
// SSH_MSG_USERAUTH_FAILURE (rfc4252 #8 [password] and rfc4256 #3.4
|
||||
// [keyboard-interactive]); Without this decorator, the non-retryable
|
||||
// AuthMethod would be removed from future consideration, and never tried again
|
||||
// (and so the user would never be able to retry their entry).
|
||||
func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod {
|
||||
return &retryableAuthMethod{authMethod: auth, maxTries: maxTries}
|
||||
}
|
||||
|
||||
81
vendor/golang.org/x/crypto/ssh/client_auth_test.go
сгенерированный
поставляемый
81
vendor/golang.org/x/crypto/ssh/client_auth_test.go
сгенерированный
поставляемый
@@ -9,6 +9,7 @@ import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
@@ -243,6 +244,9 @@ func TestClientUnsupportedCipher(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestClientUnsupportedKex(t *testing.T) {
|
||||
if os.Getenv("GO_BUILDER_NAME") != "" {
|
||||
t.Skip("skipping known-flaky test on the Go build dashboard; see golang.org/issue/15198")
|
||||
}
|
||||
config := &ClientConfig{
|
||||
User: "testuser",
|
||||
Auth: []AuthMethod{
|
||||
@@ -296,7 +300,7 @@ func TestClientLoginCert(t *testing.T) {
|
||||
t.Log("sign with wrong key")
|
||||
cert.SignCert(rand.Reader, testSigners["dsa"])
|
||||
if err := tryAuth(t, clientConfig); err == nil {
|
||||
t.Errorf("cert login passed with non-authoritive key")
|
||||
t.Errorf("cert login passed with non-authoritative key")
|
||||
}
|
||||
|
||||
t.Log("host cert")
|
||||
@@ -391,3 +395,78 @@ func TestPermissionsPassing(t *testing.T) {
|
||||
func TestNoPermissionsPassing(t *testing.T) {
|
||||
testPermissionsPassing(false, t)
|
||||
}
|
||||
|
||||
func TestRetryableAuth(t *testing.T) {
|
||||
n := 0
|
||||
passwords := []string{"WRONG1", "WRONG2"}
|
||||
|
||||
config := &ClientConfig{
|
||||
User: "testuser",
|
||||
Auth: []AuthMethod{
|
||||
RetryableAuthMethod(PasswordCallback(func() (string, error) {
|
||||
p := passwords[n]
|
||||
n++
|
||||
return p, nil
|
||||
}), 2),
|
||||
PublicKeys(testSigners["rsa"]),
|
||||
},
|
||||
}
|
||||
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
t.Fatalf("unable to dial remote side: %s", err)
|
||||
}
|
||||
if n != 2 {
|
||||
t.Fatalf("Did not try all passwords")
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleRetryableAuthMethod(t *testing.T) {
|
||||
user := "testuser"
|
||||
NumberOfPrompts := 3
|
||||
|
||||
// Normally this would be a callback that prompts the user to answer the
|
||||
// provided questions
|
||||
Cb := func(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
|
||||
return []string{"answer1", "answer2"}, nil
|
||||
}
|
||||
|
||||
config := &ClientConfig{
|
||||
User: user,
|
||||
Auth: []AuthMethod{
|
||||
RetryableAuthMethod(KeyboardInteractiveChallenge(Cb), NumberOfPrompts),
|
||||
},
|
||||
}
|
||||
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
t.Fatalf("unable to dial remote side: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Test if username is received on server side when NoClientAuth is used
|
||||
func TestClientAuthNone(t *testing.T) {
|
||||
user := "testuser"
|
||||
serverConfig := &ServerConfig{
|
||||
NoClientAuth: true,
|
||||
}
|
||||
serverConfig.AddHostKey(testSigners["rsa"])
|
||||
|
||||
clientConfig := &ClientConfig{
|
||||
User: user,
|
||||
}
|
||||
|
||||
c1, c2, err := netPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("netPipe: %v", err)
|
||||
}
|
||||
defer c1.Close()
|
||||
defer c2.Close()
|
||||
|
||||
go NewClientConn(c2, "", clientConfig)
|
||||
serverConn, err := newServer(c1, serverConfig)
|
||||
if err != nil {
|
||||
t.Fatal("newServer: %v", err)
|
||||
}
|
||||
if serverConn.User() != user {
|
||||
t.Fatalf("server: got %q, want %q", serverConn.User(), user)
|
||||
}
|
||||
}
|
||||
|
||||
2
vendor/golang.org/x/crypto/ssh/common.go
сгенерированный
поставляемый
2
vendor/golang.org/x/crypto/ssh/common.go
сгенерированный
поставляемый
@@ -44,7 +44,7 @@ var supportedKexAlgos = []string{
|
||||
// of authenticating servers) in preference order.
|
||||
var supportedHostKeyAlgos = []string{
|
||||
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
|
||||
CertAlgoECDSA384v01, CertAlgoECDSA521v01,
|
||||
CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01,
|
||||
|
||||
KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
|
||||
KeyAlgoRSA, KeyAlgoDSA,
|
||||
|
||||
1
vendor/golang.org/x/crypto/ssh/connection.go
сгенерированный
поставляемый
1
vendor/golang.org/x/crypto/ssh/connection.go
сгенерированный
поставляемый
@@ -23,7 +23,6 @@ func (e *OpenChannelError) Error() string {
|
||||
// ConnMetadata holds metadata for the connection.
|
||||
type ConnMetadata interface {
|
||||
// User returns the user ID for this connection.
|
||||
// It is empty if no authentication is used.
|
||||
User() string
|
||||
|
||||
// SessionID returns the sesson hash, also denoted by H.
|
||||
|
||||
43
vendor/golang.org/x/crypto/ssh/handshake.go
сгенерированный
поставляемый
43
vendor/golang.org/x/crypto/ssh/handshake.go
сгенерированный
поставляемый
@@ -174,15 +174,7 @@ func (t *handshakeTransport) readOnePacket() ([]byte, error) {
|
||||
|
||||
t.mu.Lock()
|
||||
|
||||
// By default, a key exchange is hidden from higher layers by
|
||||
// translating it into msgIgnore.
|
||||
successPacket := []byte{msgIgnore}
|
||||
if t.sessionID == nil {
|
||||
// sendKexInit() for the first kex waits for
|
||||
// msgNewKeys so the authentication process is
|
||||
// guaranteed to happen over an encrypted transport.
|
||||
successPacket = []byte{msgNewKeys}
|
||||
}
|
||||
firstKex := t.sessionID == nil
|
||||
|
||||
err = t.enterKeyExchangeLocked(p)
|
||||
if err != nil {
|
||||
@@ -192,7 +184,7 @@ func (t *handshakeTransport) readOnePacket() ([]byte, error) {
|
||||
}
|
||||
|
||||
if debugHandshake {
|
||||
log.Printf("%s exited key exchange, err %v", t.id(), err)
|
||||
log.Printf("%s exited key exchange (first %v), err %v", t.id(), firstKex, err)
|
||||
}
|
||||
|
||||
// Unblock writers.
|
||||
@@ -207,6 +199,17 @@ func (t *handshakeTransport) readOnePacket() ([]byte, error) {
|
||||
}
|
||||
|
||||
t.readSinceKex = 0
|
||||
|
||||
// By default, a key exchange is hidden from higher layers by
|
||||
// translating it into msgIgnore.
|
||||
successPacket := []byte{msgIgnore}
|
||||
if firstKex {
|
||||
// sendKexInit() for the first kex waits for
|
||||
// msgNewKeys so the authentication process is
|
||||
// guaranteed to happen over an encrypted transport.
|
||||
successPacket = []byte{msgNewKeys}
|
||||
}
|
||||
|
||||
return successPacket, nil
|
||||
}
|
||||
|
||||
@@ -225,16 +228,15 @@ const (
|
||||
// close the underlying transport. This function is safe for
|
||||
// concurrent use by multiple goroutines.
|
||||
func (t *handshakeTransport) sendKexInit(isFirst keyChangeCategory) error {
|
||||
var err error
|
||||
|
||||
t.mu.Lock()
|
||||
// If this is the initial key change, but we already have a sessionID,
|
||||
// then do nothing because the key exchange has already completed
|
||||
// asynchronously.
|
||||
if isFirst && t.sessionID != nil {
|
||||
t.mu.Unlock()
|
||||
return nil
|
||||
if !isFirst || t.sessionID == nil {
|
||||
_, _, err = t.sendKexInitLocked(isFirst)
|
||||
}
|
||||
|
||||
_, _, err := t.sendKexInitLocked(isFirst)
|
||||
t.mu.Unlock()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -369,7 +371,16 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro
|
||||
}
|
||||
|
||||
// We don't send FirstKexFollows, but we handle receiving it.
|
||||
if otherInit.FirstKexFollows && algs.kex != otherInit.KexAlgos[0] {
|
||||
//
|
||||
// RFC 4253 section 7 defines the kex and the agreement method for
|
||||
// first_kex_packet_follows. It states that the guessed packet
|
||||
// should be ignored if the "kex algorithm and/or the host
|
||||
// key algorithm is guessed wrong (server and client have
|
||||
// different preferred algorithm), or if any of the other
|
||||
// algorithms cannot be agreed upon". The other algorithms have
|
||||
// already been checked above so the kex algorithm and host key
|
||||
// algorithm are checked here.
|
||||
if otherInit.FirstKexFollows && (clientInit.KexAlgos[0] != serverInit.KexAlgos[0] || clientInit.ServerHostKeyAlgos[0] != serverInit.ServerHostKeyAlgos[0]) {
|
||||
// other side sent a kex message for the wrong algorithm,
|
||||
// which we have to ignore.
|
||||
if _, err := t.conn.readPacket(); err != nil {
|
||||
|
||||
2
vendor/golang.org/x/crypto/ssh/keys.go
сгенерированный
поставляемый
2
vendor/golang.org/x/crypto/ssh/keys.go
сгенерированный
поставляемый
@@ -125,7 +125,7 @@ func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey
|
||||
continue
|
||||
}
|
||||
|
||||
// Strip out the begining of the known_host key.
|
||||
// Strip out the beginning of the known_host key.
|
||||
// This is either an optional marker or a (set of) hostname(s).
|
||||
keyFields := bytes.Fields(in)
|
||||
if len(keyFields) < 3 || len(keyFields) > 5 {
|
||||
|
||||
1
vendor/golang.org/x/crypto/ssh/server.go
сгенерированный
поставляемый
1
vendor/golang.org/x/crypto/ssh/server.go
сгенерированный
поставляемый
@@ -284,7 +284,6 @@ userAuthLoop:
|
||||
switch userAuthReq.Method {
|
||||
case "none":
|
||||
if config.NoClientAuth {
|
||||
s.user = ""
|
||||
authErr = nil
|
||||
}
|
||||
case "password":
|
||||
|
||||
33
vendor/golang.org/x/crypto/ssh/session.go
сгенерированный
поставляемый
33
vendor/golang.org/x/crypto/ssh/session.go
сгенерированный
поставляемый
@@ -9,6 +9,7 @@ package ssh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -281,9 +282,10 @@ func (s *Session) Start(cmd string) error {
|
||||
// copying stdin, stdout, and stderr, and exits with a zero exit
|
||||
// status.
|
||||
//
|
||||
// If the command fails to run or doesn't complete successfully, the
|
||||
// error is of type *ExitError. Other error types may be
|
||||
// returned for I/O problems.
|
||||
// If the remote server does not send an exit status, an error of type
|
||||
// *ExitMissingError is returned. If the command completes
|
||||
// unsuccessfully or is interrupted by a signal, the error is of type
|
||||
// *ExitError. Other error types may be returned for I/O problems.
|
||||
func (s *Session) Run(cmd string) error {
|
||||
err := s.Start(cmd)
|
||||
if err != nil {
|
||||
@@ -370,9 +372,10 @@ func (s *Session) start() error {
|
||||
// copying stdin, stdout, and stderr, and exits with a zero exit
|
||||
// status.
|
||||
//
|
||||
// If the command fails to run or doesn't complete successfully, the
|
||||
// error is of type *ExitError. Other error types may be
|
||||
// returned for I/O problems.
|
||||
// If the remote server does not send an exit status, an error of type
|
||||
// *ExitMissingError is returned. If the command completes
|
||||
// unsuccessfully or is interrupted by a signal, the error is of type
|
||||
// *ExitError. Other error types may be returned for I/O problems.
|
||||
func (s *Session) Wait() error {
|
||||
if !s.started {
|
||||
return errors.New("ssh: session not started")
|
||||
@@ -400,8 +403,7 @@ func (s *Session) wait(reqs <-chan *Request) error {
|
||||
for msg := range reqs {
|
||||
switch msg.Type {
|
||||
case "exit-status":
|
||||
d := msg.Payload
|
||||
wm.status = int(d[0])<<24 | int(d[1])<<16 | int(d[2])<<8 | int(d[3])
|
||||
wm.status = int(binary.BigEndian.Uint32(msg.Payload))
|
||||
case "exit-signal":
|
||||
var sigval struct {
|
||||
Signal string
|
||||
@@ -431,16 +433,29 @@ func (s *Session) wait(reqs <-chan *Request) error {
|
||||
if wm.status == -1 {
|
||||
// exit-status was never sent from server
|
||||
if wm.signal == "" {
|
||||
return errors.New("wait: remote command exited without exit status or exit signal")
|
||||
// signal was not sent either. RFC 4254
|
||||
// section 6.10 recommends against this
|
||||
// behavior, but it is allowed, so we let
|
||||
// clients handle it.
|
||||
return &ExitMissingError{}
|
||||
}
|
||||
wm.status = 128
|
||||
if _, ok := signals[Signal(wm.signal)]; ok {
|
||||
wm.status += signals[Signal(wm.signal)]
|
||||
}
|
||||
}
|
||||
|
||||
return &ExitError{wm}
|
||||
}
|
||||
|
||||
// ExitMissingError is returned if a session is torn down cleanly, but
|
||||
// the server sends no confirmation of the exit status.
|
||||
type ExitMissingError struct{}
|
||||
|
||||
func (e *ExitMissingError) Error() string {
|
||||
return "wait: remote command exited without exit status or exit signal"
|
||||
}
|
||||
|
||||
func (s *Session) stdin() {
|
||||
if s.stdinpipe {
|
||||
return
|
||||
|
||||
8
vendor/golang.org/x/crypto/ssh/session_test.go
сгенерированный
поставляемый
8
vendor/golang.org/x/crypto/ssh/session_test.go
сгенерированный
поставляемый
@@ -297,7 +297,6 @@ func TestUnknownExitSignal(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test WaitMsg is not returned if the channel closes abruptly.
|
||||
func TestExitWithoutStatusOrSignal(t *testing.T) {
|
||||
conn := dial(exitWithoutSignalOrStatus, t)
|
||||
defer conn.Close()
|
||||
@@ -313,11 +312,8 @@ func TestExitWithoutStatusOrSignal(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Fatalf("expected command to fail but it didn't")
|
||||
}
|
||||
_, ok := err.(*ExitError)
|
||||
if ok {
|
||||
// you can't actually test for errors.errorString
|
||||
// because it's not exported.
|
||||
t.Fatalf("expected *errorString but got %T", err)
|
||||
if _, ok := err.(*ExitMissingError); !ok {
|
||||
t.Fatalf("got %T want *ExitMissingError", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
9
vendor/golang.org/x/crypto/ssh/terminal/util.go
сгенерированный
поставляемый
9
vendor/golang.org/x/crypto/ssh/terminal/util.go
сгенерированный
поставляемый
@@ -44,8 +44,13 @@ func MakeRaw(fd int) (*State, error) {
|
||||
}
|
||||
|
||||
newState := oldState.termios
|
||||
newState.Iflag &^= syscall.ISTRIP | syscall.INLCR | syscall.ICRNL | syscall.IGNCR | syscall.IXON | syscall.IXOFF
|
||||
newState.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.ISIG
|
||||
// This attempts to replicate the behaviour documented for cfmakeraw in
|
||||
// the termios(3) manpage.
|
||||
newState.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON
|
||||
newState.Oflag &^= syscall.OPOST
|
||||
newState.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN
|
||||
newState.Cflag &^= syscall.CSIZE | syscall.PARENB
|
||||
newState.Cflag |= syscall.CS8
|
||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
10
vendor/golang.org/x/crypto/ssh/test/session_test.go
сгенерированный
поставляемый
10
vendor/golang.org/x/crypto/ssh/test/session_test.go
сгенерированный
поставляемый
@@ -280,16 +280,16 @@ func TestCiphers(t *testing.T) {
|
||||
var config ssh.Config
|
||||
config.SetDefaults()
|
||||
cipherOrder := config.Ciphers
|
||||
// This cipher will not be tested when commented out in cipher.go it will
|
||||
// These ciphers will not be tested when commented out in cipher.go it will
|
||||
// fallback to the next available as per line 292.
|
||||
cipherOrder = append(cipherOrder, "aes128-cbc")
|
||||
cipherOrder = append(cipherOrder, "aes128-cbc", "3des-cbc")
|
||||
|
||||
for _, ciph := range cipherOrder {
|
||||
server := newServer(t)
|
||||
defer server.Shutdown()
|
||||
conf := clientConfig()
|
||||
conf.Ciphers = []string{ciph}
|
||||
// Don't fail if sshd doesnt have the cipher.
|
||||
// Don't fail if sshd doesn't have the cipher.
|
||||
conf.Ciphers = append(conf.Ciphers, cipherOrder...)
|
||||
conn, err := server.TryDial(conf)
|
||||
if err == nil {
|
||||
@@ -310,7 +310,7 @@ func TestMACs(t *testing.T) {
|
||||
defer server.Shutdown()
|
||||
conf := clientConfig()
|
||||
conf.MACs = []string{mac}
|
||||
// Don't fail if sshd doesnt have the MAC.
|
||||
// Don't fail if sshd doesn't have the MAC.
|
||||
conf.MACs = append(conf.MACs, macOrder...)
|
||||
if conn, err := server.TryDial(conf); err == nil {
|
||||
conn.Close()
|
||||
@@ -328,7 +328,7 @@ func TestKeyExchanges(t *testing.T) {
|
||||
server := newServer(t)
|
||||
defer server.Shutdown()
|
||||
conf := clientConfig()
|
||||
// Don't fail if sshd doesnt have the kex.
|
||||
// Don't fail if sshd doesn't have the kex.
|
||||
conf.KeyExchanges = append([]string{kex}, kexOrder...)
|
||||
conn, err := server.TryDial(conf)
|
||||
if err == nil {
|
||||
|
||||
2
vendor/golang.org/x/crypto/ssh/test/testdata_test.go
сгенерированный
поставляемый
2
vendor/golang.org/x/crypto/ssh/test/testdata_test.go
сгенерированный
поставляемый
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// IMPLEMENTOR NOTE: To avoid a package loop, this file is in three places:
|
||||
// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places:
|
||||
// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three
|
||||
// instances.
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/ssh/testdata_test.go
сгенерированный
поставляемый
2
vendor/golang.org/x/crypto/ssh/testdata_test.go
сгенерированный
поставляемый
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// IMPLEMENTOR NOTE: To avoid a package loop, this file is in three places:
|
||||
// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places:
|
||||
// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three
|
||||
// instances.
|
||||
|
||||
|
||||
9
vendor/golang.org/x/crypto/ssh/transport.go
сгенерированный
поставляемый
9
vendor/golang.org/x/crypto/ssh/transport.go
сгенерированный
поставляемый
@@ -11,8 +11,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
gcmCipherID = "aes128-gcm@openssh.com"
|
||||
aes128cbcID = "aes128-cbc"
|
||||
gcmCipherID = "aes128-gcm@openssh.com"
|
||||
aes128cbcID = "aes128-cbc"
|
||||
tripledescbcID = "3des-cbc"
|
||||
)
|
||||
|
||||
// packetConn represents a transport that implements packet based
|
||||
@@ -219,6 +220,10 @@ func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (pac
|
||||
return newAESCBCCipher(iv, key, macKey, algs)
|
||||
}
|
||||
|
||||
if algs.Cipher == tripledescbcID {
|
||||
return newTripleDESCBCCipher(iv, key, macKey, algs)
|
||||
}
|
||||
|
||||
c := &streamPacketCipher{
|
||||
mac: macModes[algs.MAC].new(macKey),
|
||||
}
|
||||
|
||||
14
vendor/golang.org/x/image/colornames/gen.go
сгенерированный
поставляемый
14
vendor/golang.org/x/image/colornames/gen.go
сгенерированный
поставляемый
@@ -143,8 +143,9 @@ func writeColorNames(w io.Writer, m map[string]color.RGBA) {
|
||||
fmt.Fprintln(w, "// Map contains named colors defined in the SVG 1.1 spec.")
|
||||
fmt.Fprintln(w, "var Map = map[string]color.RGBA{")
|
||||
for _, k := range keys {
|
||||
c := m[k]
|
||||
fmt.Fprintf(w, "%q:color.RGBA{%#02x, %#02x, %#02x, %#02x}, // rgb(%d, %d, %d)\n",
|
||||
k, m[k].R, m[k].G, m[k].B, m[k].A, m[k].R, m[k].G, m[k].B)
|
||||
k, c.R, c.G, c.B, c.A, c.R, c.G, c.B)
|
||||
}
|
||||
fmt.Fprintln(w, "}\n")
|
||||
fmt.Fprintln(w, "// Names contains the color names defined in the SVG 1.1 spec.")
|
||||
@@ -152,7 +153,16 @@ func writeColorNames(w io.Writer, m map[string]color.RGBA) {
|
||||
for _, k := range keys {
|
||||
fmt.Fprintf(w, "%q,\n", k)
|
||||
}
|
||||
fmt.Fprintln(w, "}")
|
||||
fmt.Fprintln(w, "}\n")
|
||||
fmt.Fprintln(w, "var (")
|
||||
for _, k := range keys {
|
||||
c := m[k]
|
||||
// Make the upper case version of k: "Darkred" instead of "darkred".
|
||||
k = string(k[0]-0x20) + k[1:]
|
||||
fmt.Fprintf(w, "%s=color.RGBA{%#02x, %#02x, %#02x, %#02x} // rgb(%d, %d, %d)\n",
|
||||
k, c.R, c.G, c.B, c.A, c.R, c.G, c.B)
|
||||
}
|
||||
fmt.Fprintln(w, ")")
|
||||
}
|
||||
|
||||
const url = "http://www.w3.org/TR/SVG/types.html"
|
||||
|
||||
150
vendor/golang.org/x/image/colornames/table.go
сгенерированный
поставляемый
150
vendor/golang.org/x/image/colornames/table.go
сгенерированный
поставляемый
@@ -305,3 +305,153 @@ var Names = []string{
|
||||
"yellow",
|
||||
"yellowgreen",
|
||||
}
|
||||
|
||||
var (
|
||||
Aliceblue = color.RGBA{0xf0, 0xf8, 0xff, 0xff} // rgb(240, 248, 255)
|
||||
Antiquewhite = color.RGBA{0xfa, 0xeb, 0xd7, 0xff} // rgb(250, 235, 215)
|
||||
Aqua = color.RGBA{0x00, 0xff, 0xff, 0xff} // rgb(0, 255, 255)
|
||||
Aquamarine = color.RGBA{0x7f, 0xff, 0xd4, 0xff} // rgb(127, 255, 212)
|
||||
Azure = color.RGBA{0xf0, 0xff, 0xff, 0xff} // rgb(240, 255, 255)
|
||||
Beige = color.RGBA{0xf5, 0xf5, 0xdc, 0xff} // rgb(245, 245, 220)
|
||||
Bisque = color.RGBA{0xff, 0xe4, 0xc4, 0xff} // rgb(255, 228, 196)
|
||||
Black = color.RGBA{0x00, 0x00, 0x00, 0xff} // rgb(0, 0, 0)
|
||||
Blanchedalmond = color.RGBA{0xff, 0xeb, 0xcd, 0xff} // rgb(255, 235, 205)
|
||||
Blue = color.RGBA{0x00, 0x00, 0xff, 0xff} // rgb(0, 0, 255)
|
||||
Blueviolet = color.RGBA{0x8a, 0x2b, 0xe2, 0xff} // rgb(138, 43, 226)
|
||||
Brown = color.RGBA{0xa5, 0x2a, 0x2a, 0xff} // rgb(165, 42, 42)
|
||||
Burlywood = color.RGBA{0xde, 0xb8, 0x87, 0xff} // rgb(222, 184, 135)
|
||||
Cadetblue = color.RGBA{0x5f, 0x9e, 0xa0, 0xff} // rgb(95, 158, 160)
|
||||
Chartreuse = color.RGBA{0x7f, 0xff, 0x00, 0xff} // rgb(127, 255, 0)
|
||||
Chocolate = color.RGBA{0xd2, 0x69, 0x1e, 0xff} // rgb(210, 105, 30)
|
||||
Coral = color.RGBA{0xff, 0x7f, 0x50, 0xff} // rgb(255, 127, 80)
|
||||
Cornflowerblue = color.RGBA{0x64, 0x95, 0xed, 0xff} // rgb(100, 149, 237)
|
||||
Cornsilk = color.RGBA{0xff, 0xf8, 0xdc, 0xff} // rgb(255, 248, 220)
|
||||
Crimson = color.RGBA{0xdc, 0x14, 0x3c, 0xff} // rgb(220, 20, 60)
|
||||
Cyan = color.RGBA{0x00, 0xff, 0xff, 0xff} // rgb(0, 255, 255)
|
||||
Darkblue = color.RGBA{0x00, 0x00, 0x8b, 0xff} // rgb(0, 0, 139)
|
||||
Darkcyan = color.RGBA{0x00, 0x8b, 0x8b, 0xff} // rgb(0, 139, 139)
|
||||
Darkgoldenrod = color.RGBA{0xb8, 0x86, 0x0b, 0xff} // rgb(184, 134, 11)
|
||||
Darkgray = color.RGBA{0xa9, 0xa9, 0xa9, 0xff} // rgb(169, 169, 169)
|
||||
Darkgreen = color.RGBA{0x00, 0x64, 0x00, 0xff} // rgb(0, 100, 0)
|
||||
Darkgrey = color.RGBA{0xa9, 0xa9, 0xa9, 0xff} // rgb(169, 169, 169)
|
||||
Darkkhaki = color.RGBA{0xbd, 0xb7, 0x6b, 0xff} // rgb(189, 183, 107)
|
||||
Darkmagenta = color.RGBA{0x8b, 0x00, 0x8b, 0xff} // rgb(139, 0, 139)
|
||||
Darkolivegreen = color.RGBA{0x55, 0x6b, 0x2f, 0xff} // rgb(85, 107, 47)
|
||||
Darkorange = color.RGBA{0xff, 0x8c, 0x00, 0xff} // rgb(255, 140, 0)
|
||||
Darkorchid = color.RGBA{0x99, 0x32, 0xcc, 0xff} // rgb(153, 50, 204)
|
||||
Darkred = color.RGBA{0x8b, 0x00, 0x00, 0xff} // rgb(139, 0, 0)
|
||||
Darksalmon = color.RGBA{0xe9, 0x96, 0x7a, 0xff} // rgb(233, 150, 122)
|
||||
Darkseagreen = color.RGBA{0x8f, 0xbc, 0x8f, 0xff} // rgb(143, 188, 143)
|
||||
Darkslateblue = color.RGBA{0x48, 0x3d, 0x8b, 0xff} // rgb(72, 61, 139)
|
||||
Darkslategray = color.RGBA{0x2f, 0x4f, 0x4f, 0xff} // rgb(47, 79, 79)
|
||||
Darkslategrey = color.RGBA{0x2f, 0x4f, 0x4f, 0xff} // rgb(47, 79, 79)
|
||||
Darkturquoise = color.RGBA{0x00, 0xce, 0xd1, 0xff} // rgb(0, 206, 209)
|
||||
Darkviolet = color.RGBA{0x94, 0x00, 0xd3, 0xff} // rgb(148, 0, 211)
|
||||
Deeppink = color.RGBA{0xff, 0x14, 0x93, 0xff} // rgb(255, 20, 147)
|
||||
Deepskyblue = color.RGBA{0x00, 0xbf, 0xff, 0xff} // rgb(0, 191, 255)
|
||||
Dimgray = color.RGBA{0x69, 0x69, 0x69, 0xff} // rgb(105, 105, 105)
|
||||
Dimgrey = color.RGBA{0x69, 0x69, 0x69, 0xff} // rgb(105, 105, 105)
|
||||
Dodgerblue = color.RGBA{0x1e, 0x90, 0xff, 0xff} // rgb(30, 144, 255)
|
||||
Firebrick = color.RGBA{0xb2, 0x22, 0x22, 0xff} // rgb(178, 34, 34)
|
||||
Floralwhite = color.RGBA{0xff, 0xfa, 0xf0, 0xff} // rgb(255, 250, 240)
|
||||
Forestgreen = color.RGBA{0x22, 0x8b, 0x22, 0xff} // rgb(34, 139, 34)
|
||||
Fuchsia = color.RGBA{0xff, 0x00, 0xff, 0xff} // rgb(255, 0, 255)
|
||||
Gainsboro = color.RGBA{0xdc, 0xdc, 0xdc, 0xff} // rgb(220, 220, 220)
|
||||
Ghostwhite = color.RGBA{0xf8, 0xf8, 0xff, 0xff} // rgb(248, 248, 255)
|
||||
Gold = color.RGBA{0xff, 0xd7, 0x00, 0xff} // rgb(255, 215, 0)
|
||||
Goldenrod = color.RGBA{0xda, 0xa5, 0x20, 0xff} // rgb(218, 165, 32)
|
||||
Gray = color.RGBA{0x80, 0x80, 0x80, 0xff} // rgb(128, 128, 128)
|
||||
Green = color.RGBA{0x00, 0x80, 0x00, 0xff} // rgb(0, 128, 0)
|
||||
Greenyellow = color.RGBA{0xad, 0xff, 0x2f, 0xff} // rgb(173, 255, 47)
|
||||
Grey = color.RGBA{0x80, 0x80, 0x80, 0xff} // rgb(128, 128, 128)
|
||||
Honeydew = color.RGBA{0xf0, 0xff, 0xf0, 0xff} // rgb(240, 255, 240)
|
||||
Hotpink = color.RGBA{0xff, 0x69, 0xb4, 0xff} // rgb(255, 105, 180)
|
||||
Indianred = color.RGBA{0xcd, 0x5c, 0x5c, 0xff} // rgb(205, 92, 92)
|
||||
Indigo = color.RGBA{0x4b, 0x00, 0x82, 0xff} // rgb(75, 0, 130)
|
||||
Ivory = color.RGBA{0xff, 0xff, 0xf0, 0xff} // rgb(255, 255, 240)
|
||||
Khaki = color.RGBA{0xf0, 0xe6, 0x8c, 0xff} // rgb(240, 230, 140)
|
||||
Lavender = color.RGBA{0xe6, 0xe6, 0xfa, 0xff} // rgb(230, 230, 250)
|
||||
Lavenderblush = color.RGBA{0xff, 0xf0, 0xf5, 0xff} // rgb(255, 240, 245)
|
||||
Lawngreen = color.RGBA{0x7c, 0xfc, 0x00, 0xff} // rgb(124, 252, 0)
|
||||
Lemonchiffon = color.RGBA{0xff, 0xfa, 0xcd, 0xff} // rgb(255, 250, 205)
|
||||
Lightblue = color.RGBA{0xad, 0xd8, 0xe6, 0xff} // rgb(173, 216, 230)
|
||||
Lightcoral = color.RGBA{0xf0, 0x80, 0x80, 0xff} // rgb(240, 128, 128)
|
||||
Lightcyan = color.RGBA{0xe0, 0xff, 0xff, 0xff} // rgb(224, 255, 255)
|
||||
Lightgoldenrodyellow = color.RGBA{0xfa, 0xfa, 0xd2, 0xff} // rgb(250, 250, 210)
|
||||
Lightgray = color.RGBA{0xd3, 0xd3, 0xd3, 0xff} // rgb(211, 211, 211)
|
||||
Lightgreen = color.RGBA{0x90, 0xee, 0x90, 0xff} // rgb(144, 238, 144)
|
||||
Lightgrey = color.RGBA{0xd3, 0xd3, 0xd3, 0xff} // rgb(211, 211, 211)
|
||||
Lightpink = color.RGBA{0xff, 0xb6, 0xc1, 0xff} // rgb(255, 182, 193)
|
||||
Lightsalmon = color.RGBA{0xff, 0xa0, 0x7a, 0xff} // rgb(255, 160, 122)
|
||||
Lightseagreen = color.RGBA{0x20, 0xb2, 0xaa, 0xff} // rgb(32, 178, 170)
|
||||
Lightskyblue = color.RGBA{0x87, 0xce, 0xfa, 0xff} // rgb(135, 206, 250)
|
||||
Lightslategray = color.RGBA{0x77, 0x88, 0x99, 0xff} // rgb(119, 136, 153)
|
||||
Lightslategrey = color.RGBA{0x77, 0x88, 0x99, 0xff} // rgb(119, 136, 153)
|
||||
Lightsteelblue = color.RGBA{0xb0, 0xc4, 0xde, 0xff} // rgb(176, 196, 222)
|
||||
Lightyellow = color.RGBA{0xff, 0xff, 0xe0, 0xff} // rgb(255, 255, 224)
|
||||
Lime = color.RGBA{0x00, 0xff, 0x00, 0xff} // rgb(0, 255, 0)
|
||||
Limegreen = color.RGBA{0x32, 0xcd, 0x32, 0xff} // rgb(50, 205, 50)
|
||||
Linen = color.RGBA{0xfa, 0xf0, 0xe6, 0xff} // rgb(250, 240, 230)
|
||||
Magenta = color.RGBA{0xff, 0x00, 0xff, 0xff} // rgb(255, 0, 255)
|
||||
Maroon = color.RGBA{0x80, 0x00, 0x00, 0xff} // rgb(128, 0, 0)
|
||||
Mediumaquamarine = color.RGBA{0x66, 0xcd, 0xaa, 0xff} // rgb(102, 205, 170)
|
||||
Mediumblue = color.RGBA{0x00, 0x00, 0xcd, 0xff} // rgb(0, 0, 205)
|
||||
Mediumorchid = color.RGBA{0xba, 0x55, 0xd3, 0xff} // rgb(186, 85, 211)
|
||||
Mediumpurple = color.RGBA{0x93, 0x70, 0xdb, 0xff} // rgb(147, 112, 219)
|
||||
Mediumseagreen = color.RGBA{0x3c, 0xb3, 0x71, 0xff} // rgb(60, 179, 113)
|
||||
Mediumslateblue = color.RGBA{0x7b, 0x68, 0xee, 0xff} // rgb(123, 104, 238)
|
||||
Mediumspringgreen = color.RGBA{0x00, 0xfa, 0x9a, 0xff} // rgb(0, 250, 154)
|
||||
Mediumturquoise = color.RGBA{0x48, 0xd1, 0xcc, 0xff} // rgb(72, 209, 204)
|
||||
Mediumvioletred = color.RGBA{0xc7, 0x15, 0x85, 0xff} // rgb(199, 21, 133)
|
||||
Midnightblue = color.RGBA{0x19, 0x19, 0x70, 0xff} // rgb(25, 25, 112)
|
||||
Mintcream = color.RGBA{0xf5, 0xff, 0xfa, 0xff} // rgb(245, 255, 250)
|
||||
Mistyrose = color.RGBA{0xff, 0xe4, 0xe1, 0xff} // rgb(255, 228, 225)
|
||||
Moccasin = color.RGBA{0xff, 0xe4, 0xb5, 0xff} // rgb(255, 228, 181)
|
||||
Navajowhite = color.RGBA{0xff, 0xde, 0xad, 0xff} // rgb(255, 222, 173)
|
||||
Navy = color.RGBA{0x00, 0x00, 0x80, 0xff} // rgb(0, 0, 128)
|
||||
Oldlace = color.RGBA{0xfd, 0xf5, 0xe6, 0xff} // rgb(253, 245, 230)
|
||||
Olive = color.RGBA{0x80, 0x80, 0x00, 0xff} // rgb(128, 128, 0)
|
||||
Olivedrab = color.RGBA{0x6b, 0x8e, 0x23, 0xff} // rgb(107, 142, 35)
|
||||
Orange = color.RGBA{0xff, 0xa5, 0x00, 0xff} // rgb(255, 165, 0)
|
||||
Orangered = color.RGBA{0xff, 0x45, 0x00, 0xff} // rgb(255, 69, 0)
|
||||
Orchid = color.RGBA{0xda, 0x70, 0xd6, 0xff} // rgb(218, 112, 214)
|
||||
Palegoldenrod = color.RGBA{0xee, 0xe8, 0xaa, 0xff} // rgb(238, 232, 170)
|
||||
Palegreen = color.RGBA{0x98, 0xfb, 0x98, 0xff} // rgb(152, 251, 152)
|
||||
Paleturquoise = color.RGBA{0xaf, 0xee, 0xee, 0xff} // rgb(175, 238, 238)
|
||||
Palevioletred = color.RGBA{0xdb, 0x70, 0x93, 0xff} // rgb(219, 112, 147)
|
||||
Papayawhip = color.RGBA{0xff, 0xef, 0xd5, 0xff} // rgb(255, 239, 213)
|
||||
Peachpuff = color.RGBA{0xff, 0xda, 0xb9, 0xff} // rgb(255, 218, 185)
|
||||
Peru = color.RGBA{0xcd, 0x85, 0x3f, 0xff} // rgb(205, 133, 63)
|
||||
Pink = color.RGBA{0xff, 0xc0, 0xcb, 0xff} // rgb(255, 192, 203)
|
||||
Plum = color.RGBA{0xdd, 0xa0, 0xdd, 0xff} // rgb(221, 160, 221)
|
||||
Powderblue = color.RGBA{0xb0, 0xe0, 0xe6, 0xff} // rgb(176, 224, 230)
|
||||
Purple = color.RGBA{0x80, 0x00, 0x80, 0xff} // rgb(128, 0, 128)
|
||||
Red = color.RGBA{0xff, 0x00, 0x00, 0xff} // rgb(255, 0, 0)
|
||||
Rosybrown = color.RGBA{0xbc, 0x8f, 0x8f, 0xff} // rgb(188, 143, 143)
|
||||
Royalblue = color.RGBA{0x41, 0x69, 0xe1, 0xff} // rgb(65, 105, 225)
|
||||
Saddlebrown = color.RGBA{0x8b, 0x45, 0x13, 0xff} // rgb(139, 69, 19)
|
||||
Salmon = color.RGBA{0xfa, 0x80, 0x72, 0xff} // rgb(250, 128, 114)
|
||||
Sandybrown = color.RGBA{0xf4, 0xa4, 0x60, 0xff} // rgb(244, 164, 96)
|
||||
Seagreen = color.RGBA{0x2e, 0x8b, 0x57, 0xff} // rgb(46, 139, 87)
|
||||
Seashell = color.RGBA{0xff, 0xf5, 0xee, 0xff} // rgb(255, 245, 238)
|
||||
Sienna = color.RGBA{0xa0, 0x52, 0x2d, 0xff} // rgb(160, 82, 45)
|
||||
Silver = color.RGBA{0xc0, 0xc0, 0xc0, 0xff} // rgb(192, 192, 192)
|
||||
Skyblue = color.RGBA{0x87, 0xce, 0xeb, 0xff} // rgb(135, 206, 235)
|
||||
Slateblue = color.RGBA{0x6a, 0x5a, 0xcd, 0xff} // rgb(106, 90, 205)
|
||||
Slategray = color.RGBA{0x70, 0x80, 0x90, 0xff} // rgb(112, 128, 144)
|
||||
Slategrey = color.RGBA{0x70, 0x80, 0x90, 0xff} // rgb(112, 128, 144)
|
||||
Snow = color.RGBA{0xff, 0xfa, 0xfa, 0xff} // rgb(255, 250, 250)
|
||||
Springgreen = color.RGBA{0x00, 0xff, 0x7f, 0xff} // rgb(0, 255, 127)
|
||||
Steelblue = color.RGBA{0x46, 0x82, 0xb4, 0xff} // rgb(70, 130, 180)
|
||||
Tan = color.RGBA{0xd2, 0xb4, 0x8c, 0xff} // rgb(210, 180, 140)
|
||||
Teal = color.RGBA{0x00, 0x80, 0x80, 0xff} // rgb(0, 128, 128)
|
||||
Thistle = color.RGBA{0xd8, 0xbf, 0xd8, 0xff} // rgb(216, 191, 216)
|
||||
Tomato = color.RGBA{0xff, 0x63, 0x47, 0xff} // rgb(255, 99, 71)
|
||||
Turquoise = color.RGBA{0x40, 0xe0, 0xd0, 0xff} // rgb(64, 224, 208)
|
||||
Violet = color.RGBA{0xee, 0x82, 0xee, 0xff} // rgb(238, 130, 238)
|
||||
Wheat = color.RGBA{0xf5, 0xde, 0xb3, 0xff} // rgb(245, 222, 179)
|
||||
White = color.RGBA{0xff, 0xff, 0xff, 0xff} // rgb(255, 255, 255)
|
||||
Whitesmoke = color.RGBA{0xf5, 0xf5, 0xf5, 0xff} // rgb(245, 245, 245)
|
||||
Yellow = color.RGBA{0xff, 0xff, 0x00, 0xff} // rgb(255, 255, 0)
|
||||
Yellowgreen = color.RGBA{0x9a, 0xcd, 0x32, 0xff} // rgb(154, 205, 50)
|
||||
)
|
||||
|
||||
32
vendor/golang.org/x/image/font/basicfont/basicfont.go
сгенерированный
поставляемый
32
vendor/golang.org/x/image/font/basicfont/basicfont.go
сгенерированный
поставляемый
@@ -19,8 +19,8 @@ import (
|
||||
// exclusive on the high end.
|
||||
//
|
||||
// If Low <= r && r < High, then the rune r is mapped to the sub-image of
|
||||
// Face.Mask whose bounds are image.Rect(0, y, Face.Width, y+Face.Height),
|
||||
// where y equals (int(r-Low) + Offset) * Face.Height.
|
||||
// Face.Mask whose bounds are image.Rect(0, y*h, Face.Width, (y+1)*h),
|
||||
// where y = (int(r-Low) + Offset) and h = (Face.Ascent + Face.Descent).
|
||||
type Range struct {
|
||||
Low, High rune
|
||||
Offset int
|
||||
@@ -38,6 +38,7 @@ var Face7x13 = &Face{
|
||||
Width: 6,
|
||||
Height: 13,
|
||||
Ascent: 11,
|
||||
Descent: 2,
|
||||
Mask: mask7x13,
|
||||
Ranges: []Range{
|
||||
{'\u0020', '\u007f', 0},
|
||||
@@ -53,12 +54,15 @@ type Face struct {
|
||||
Advance int
|
||||
// Width is the glyph width, in pixels.
|
||||
Width int
|
||||
// Height is the glyph height, in pixels.
|
||||
// Height is the inter-line height, in pixels.
|
||||
Height int
|
||||
// Ascent is the glyph ascent, in pixels.
|
||||
Ascent int
|
||||
|
||||
// TODO: do we also need Top and Left fields?
|
||||
// Descent is the glyph descent, in pixels.
|
||||
Descent int
|
||||
// Left is the left side bearing, in pixels. A positive value means that
|
||||
// all of a glyph is to the right of the dot.
|
||||
Left int
|
||||
|
||||
// Mask contains all of the glyph masks. Its width is typically the Face's
|
||||
// Width, and its height a multiple of the Face's Height.
|
||||
@@ -75,7 +79,7 @@ func (f *Face) Metrics() font.Metrics {
|
||||
return font.Metrics{
|
||||
Height: fixed.I(f.Height),
|
||||
Ascent: fixed.I(f.Ascent),
|
||||
Descent: fixed.I(f.Height - f.Ascent),
|
||||
Descent: fixed.I(f.Descent),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +92,7 @@ loop:
|
||||
if rr < rng.Low || rng.High <= rr {
|
||||
continue
|
||||
}
|
||||
maskp.Y = (int(rr-rng.Low) + rng.Offset) * f.Height
|
||||
maskp.Y = (int(rr-rng.Low) + rng.Offset) * (f.Ascent + f.Descent)
|
||||
ok = true
|
||||
break loop
|
||||
}
|
||||
@@ -97,16 +101,16 @@ loop:
|
||||
return image.Rectangle{}, nil, image.Point{}, 0, false
|
||||
}
|
||||
|
||||
minX := int(dot.X+32) >> 6
|
||||
minY := int(dot.Y+32)>>6 - f.Ascent
|
||||
x := int(dot.X+32)>>6 + f.Left
|
||||
y := int(dot.Y+32) >> 6
|
||||
dr = image.Rectangle{
|
||||
Min: image.Point{
|
||||
X: minX,
|
||||
Y: minY,
|
||||
X: x,
|
||||
Y: y - f.Ascent,
|
||||
},
|
||||
Max: image.Point{
|
||||
X: minX + f.Width,
|
||||
Y: minY + f.Height,
|
||||
X: x + f.Width,
|
||||
Y: y + f.Descent,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -114,7 +118,7 @@ loop:
|
||||
}
|
||||
|
||||
func (f *Face) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
|
||||
return fixed.R(0, -f.Ascent, f.Width, -f.Ascent+f.Height), fixed.I(f.Advance), true
|
||||
return fixed.R(0, -f.Ascent, f.Width, +f.Descent), fixed.I(f.Advance), true
|
||||
}
|
||||
|
||||
func (f *Face) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
|
||||
|
||||
79
vendor/golang.org/x/image/font/font.go
сгенерированный
поставляемый
79
vendor/golang.org/x/image/font/font.go
сгенерированный
поставляемый
@@ -13,6 +13,7 @@ import (
|
||||
"image"
|
||||
"image/draw"
|
||||
"io"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/image/math/fixed"
|
||||
)
|
||||
@@ -87,9 +88,6 @@ type Metrics struct {
|
||||
Descent fixed.Int26_6
|
||||
}
|
||||
|
||||
// TODO: Drawer.Layout or Drawer.Measure methods to measure text without
|
||||
// drawing?
|
||||
|
||||
// Drawer draws text on a destination image.
|
||||
//
|
||||
// A Drawer is not safe for concurrent use by multiple goroutines, since its
|
||||
@@ -115,19 +113,25 @@ type Drawer struct {
|
||||
// TODO: should DrawString return the last rune drawn, so the next DrawString
|
||||
// call can kern beforehand? Or should that be the responsibility of the caller
|
||||
// if they really want to do that, since they have to explicitly shift d.Dot
|
||||
// anyway?
|
||||
// anyway? What if ligatures span more than two runes? What if grapheme
|
||||
// clusters span multiple runes?
|
||||
//
|
||||
// In general, we'd have a DrawBytes([]byte) and DrawRuneReader(io.RuneReader)
|
||||
// and the last case can't assume that you can rewind the stream.
|
||||
// TODO: do we assume that the input is in any particular Unicode Normalization
|
||||
// Form?
|
||||
//
|
||||
// TODO: have DrawRunes(s []rune)? DrawRuneReader(io.RuneReader)?? If we take
|
||||
// io.RuneReader, we can't assume that we can rewind the stream.
|
||||
//
|
||||
// TODO: how does this work with line breaking: drawing text up until a
|
||||
// vertical line? Should DrawString return the number of runes drawn?
|
||||
|
||||
// DrawString draws s at the dot and advances the dot's location.
|
||||
func (d *Drawer) DrawString(s string) {
|
||||
var prevC rune
|
||||
for i, c := range s {
|
||||
if i != 0 {
|
||||
// DrawBytes draws s at the dot and advances the dot's location.
|
||||
func (d *Drawer) DrawBytes(s []byte) {
|
||||
prevC := rune(-1)
|
||||
for len(s) > 0 {
|
||||
c, size := utf8.DecodeRune(s)
|
||||
s = s[size:]
|
||||
if prevC >= 0 {
|
||||
d.Dot.X += d.Face.Kern(prevC, c)
|
||||
}
|
||||
dr, mask, maskp, advance, ok := d.Face.Glyph(d.Dot, c)
|
||||
@@ -143,16 +147,63 @@ func (d *Drawer) DrawString(s string) {
|
||||
}
|
||||
}
|
||||
|
||||
// DrawString draws s at the dot and advances the dot's location.
|
||||
func (d *Drawer) DrawString(s string) {
|
||||
prevC := rune(-1)
|
||||
for _, c := range s {
|
||||
if prevC >= 0 {
|
||||
d.Dot.X += d.Face.Kern(prevC, c)
|
||||
}
|
||||
dr, mask, maskp, advance, ok := d.Face.Glyph(d.Dot, c)
|
||||
if !ok {
|
||||
// TODO: is falling back on the U+FFFD glyph the responsibility of
|
||||
// the Drawer or the Face?
|
||||
// TODO: set prevC = '\ufffd'?
|
||||
continue
|
||||
}
|
||||
draw.DrawMask(d.Dst, dr, d.Src, image.Point{}, mask, maskp, draw.Over)
|
||||
d.Dot.X += advance
|
||||
prevC = c
|
||||
}
|
||||
}
|
||||
|
||||
// MeasureBytes returns how far dot would advance by drawing s.
|
||||
func (d *Drawer) MeasureBytes(s []byte) (advance fixed.Int26_6) {
|
||||
return MeasureBytes(d.Face, s)
|
||||
}
|
||||
|
||||
// MeasureString returns how far dot would advance by drawing s.
|
||||
func (d *Drawer) MeasureString(s string) (advance fixed.Int26_6) {
|
||||
return MeasureString(d.Face, s)
|
||||
}
|
||||
|
||||
// MeasureBytes returns how far dot would advance by drawing s with f.
|
||||
func MeasureBytes(f Face, s []byte) (advance fixed.Int26_6) {
|
||||
prevC := rune(-1)
|
||||
for len(s) > 0 {
|
||||
c, size := utf8.DecodeRune(s)
|
||||
s = s[size:]
|
||||
if prevC >= 0 {
|
||||
advance += f.Kern(prevC, c)
|
||||
}
|
||||
a, ok := f.GlyphAdvance(c)
|
||||
if !ok {
|
||||
// TODO: is falling back on the U+FFFD glyph the responsibility of
|
||||
// the Drawer or the Face?
|
||||
// TODO: set prevC = '\ufffd'?
|
||||
continue
|
||||
}
|
||||
advance += a
|
||||
prevC = c
|
||||
}
|
||||
return advance
|
||||
}
|
||||
|
||||
// MeasureString returns how far dot would advance by drawing s with f.
|
||||
func MeasureString(f Face, s string) (advance fixed.Int26_6) {
|
||||
var prevC rune
|
||||
for i, c := range s {
|
||||
if i != 0 {
|
||||
prevC := rune(-1)
|
||||
for _, c := range s {
|
||||
if prevC >= 0 {
|
||||
advance += f.Kern(prevC, c)
|
||||
}
|
||||
a, ok := f.GlyphAdvance(c)
|
||||
|
||||
5557
vendor/golang.org/x/image/font/inconsolata/bold8x16.go
сгенерированный
поставляемый
Обычный файл
5557
vendor/golang.org/x/image/font/inconsolata/bold8x16.go
сгенерированный
поставляемый
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
29
vendor/golang.org/x/image/font/inconsolata/inconsolata.go
сгенерированный
поставляемый
Обычный файл
29
vendor/golang.org/x/image/font/inconsolata/inconsolata.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,29 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate genbasicfont -size=16 -pkg=inconsolata -hinting=full -var=regular8x16 -fontfile=http://www.levien.com/type/myfonts/inconsolata/InconsolataGo-Regular.ttf
|
||||
//go:generate genbasicfont -size=16 -pkg=inconsolata -hinting=full -var=bold8x16 -fontfile=http://www.levien.com/type/myfonts/inconsolata/InconsolataGo-Bold.ttf
|
||||
|
||||
// The genbasicfont program is github.com/golang/freetype/example/genbasicfont
|
||||
|
||||
// Package inconsolata provides pre-rendered bitmap versions of the Inconsolata
|
||||
// font family.
|
||||
//
|
||||
// Inconsolata is copyright Raph Levien and Cyreal. This package is licensed
|
||||
// under Go's BSD-style license (https://golang.org/LICENSE) with their
|
||||
// permission.
|
||||
//
|
||||
// Inconsolata's home page is at
|
||||
// http://www.levien.com/type/myfonts/inconsolata.html
|
||||
package inconsolata // import "golang.org/x/image/font/inconsolata"
|
||||
|
||||
import (
|
||||
"golang.org/x/image/font/basicfont"
|
||||
)
|
||||
|
||||
// Regular8x16 is a regular weight, 8x16 font face.
|
||||
var Regular8x16 *basicfont.Face = ®ular8x16
|
||||
|
||||
// Bold8x16 is a bold weight, 8x16 font face.
|
||||
var Bold8x16 *basicfont.Face = &bold8x16
|
||||
5557
vendor/golang.org/x/image/font/inconsolata/regular8x16.go
сгенерированный
поставляемый
Обычный файл
5557
vendor/golang.org/x/image/font/inconsolata/regular8x16.go
сгенерированный
поставляемый
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
27
vendor/golang.org/x/image/font/plan9font/plan9font.go
сгенерированный
поставляемый
27
vendor/golang.org/x/image/font/plan9font/plan9font.go
сгенерированный
поставляемый
@@ -174,6 +174,31 @@ func (f *face) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// For subfont files, if reading the given file name fails, we try appending
|
||||
// ".n" where n is the log2 of the grayscale depth in bits (so at most 3) and
|
||||
// then work down to 0. This was done in Plan 9 when antialiased fonts were
|
||||
// introduced so that the 1-bit displays could keep using the 1-bit forms but
|
||||
// higher depth displays could use the antialiased forms.
|
||||
var subfontSuffixes = [...]string{
|
||||
"",
|
||||
".3",
|
||||
".2",
|
||||
".1",
|
||||
".0",
|
||||
}
|
||||
|
||||
func (f *face) readSubfontFile(name string) ([]byte, error) {
|
||||
var firstErr error
|
||||
for _, suffix := range subfontSuffixes {
|
||||
if b, err := f.readFile(name + suffix); err == nil {
|
||||
return b, nil
|
||||
} else if firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
return nil, firstErr
|
||||
}
|
||||
|
||||
func (f *face) subface(r rune) (*subface, rune) {
|
||||
// Fall back on U+FFFD if we can't find r.
|
||||
for _, rr := range [2]rune{r, '\ufffd'} {
|
||||
@@ -188,7 +213,7 @@ func (f *face) subface(r rune) (*subface, rune) {
|
||||
continue
|
||||
}
|
||||
if x.subface == nil {
|
||||
data, err := f.readFile(x.relFilename)
|
||||
data, err := f.readSubfontFile(x.relFilename)
|
||||
if err != nil {
|
||||
log.Printf("plan9font: couldn't read subfont %q: %v", x.relFilename, err)
|
||||
x.bad = true
|
||||
|
||||
38
vendor/golang.org/x/image/math/fixed/fixed.go
сгенерированный
поставляемый
38
vendor/golang.org/x/image/math/fixed/fixed.go
сгенерированный
поставляемый
@@ -56,6 +56,11 @@ func (x Int26_6) Round() int { return int((x + 0x20) >> 6) }
|
||||
// Its return type is int, not Int26_6.
|
||||
func (x Int26_6) Ceil() int { return int((x + 0x3f) >> 6) }
|
||||
|
||||
// Mul returns x*y in 26.6 fixed-point arithmetic.
|
||||
func (x Int26_6) Mul(y Int26_6) Int26_6 {
|
||||
return Int26_6((int64(x)*int64(y) + 1<<5) >> 6)
|
||||
}
|
||||
|
||||
// Int52_12 is a signed 52.12 fixed-point number.
|
||||
//
|
||||
// The integer part ranges from -2251799813685248 to 2251799813685247,
|
||||
@@ -95,6 +100,39 @@ func (x Int52_12) Round() int { return int((x + 0x800) >> 12) }
|
||||
// Its return type is int, not Int52_12.
|
||||
func (x Int52_12) Ceil() int { return int((x + 0xfff) >> 12) }
|
||||
|
||||
// Mul returns x*y in 52.12 fixed-point arithmetic.
|
||||
func (x Int52_12) Mul(y Int52_12) Int52_12 {
|
||||
const M, N = 52, 12
|
||||
lo, hi := muli64(int64(x), int64(y))
|
||||
ret := Int52_12(hi<<M | lo>>N)
|
||||
ret += Int52_12((lo >> (N - 1)) & 1) // Round to nearest, instead of rounding down.
|
||||
return ret
|
||||
}
|
||||
|
||||
// muli64 multiplies two int64 values, returning the 128-bit signed integer
|
||||
// result as two uint64 values.
|
||||
//
|
||||
// This implementation is similar to $GOROOT/src/runtime/softfloat64.go's mullu
|
||||
// function, which is in turn adapted from Hacker's Delight.
|
||||
func muli64(u, v int64) (lo, hi uint64) {
|
||||
const (
|
||||
s = 32
|
||||
mask = 1<<s - 1
|
||||
)
|
||||
|
||||
u1 := uint64(u >> s)
|
||||
u0 := uint64(u & mask)
|
||||
v1 := uint64(v >> s)
|
||||
v0 := uint64(v & mask)
|
||||
|
||||
w0 := u0 * v0
|
||||
t := u1*v0 + w0>>s
|
||||
w1 := t & mask
|
||||
w2 := uint64(int64(t) >> s)
|
||||
w1 += u0 * v1
|
||||
return uint64(u) * uint64(v), u1*v1 + w2 + uint64(int64(w1)>>s)
|
||||
}
|
||||
|
||||
// P returns the integer values x and y as a Point26_6.
|
||||
//
|
||||
// For example, passing the integer values (2, -3) yields Point26_6{128, -192}.
|
||||
|
||||
329
vendor/golang.org/x/image/math/fixed/fixed_test.go
сгенерированный
поставляемый
329
vendor/golang.org/x/image/math/fixed/fixed_test.go
сгенерированный
поставляемый
@@ -5,6 +5,8 @@
|
||||
package fixed
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -74,6 +76,7 @@ var testCases = []struct {
|
||||
}}
|
||||
|
||||
func TestInt26_6(t *testing.T) {
|
||||
const one = Int26_6(1 << 6)
|
||||
for _, tc := range testCases {
|
||||
x := Int26_6(tc.x * (1 << 6))
|
||||
if got, want := x.String(), tc.s26_6; got != want {
|
||||
@@ -88,10 +91,17 @@ func TestInt26_6(t *testing.T) {
|
||||
if got, want := x.Ceil(), tc.ceil; got != want {
|
||||
t.Errorf("tc.x=%v: Ceil: got %v, want %v", tc.x, got, want)
|
||||
}
|
||||
if got, want := x.Mul(one), x; got != want {
|
||||
t.Errorf("tc.x=%v: Mul by one: got %v, want %v", tc.x, got, want)
|
||||
}
|
||||
if got, want := x.mul(one), x; got != want {
|
||||
t.Errorf("tc.x=%v: mul by one: got %v, want %v", tc.x, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInt52_12(t *testing.T) {
|
||||
const one = Int52_12(1 << 12)
|
||||
for _, tc := range testCases {
|
||||
x := Int52_12(tc.x * (1 << 12))
|
||||
if got, want := x.String(), tc.s52_12; got != want {
|
||||
@@ -106,5 +116,324 @@ func TestInt52_12(t *testing.T) {
|
||||
if got, want := x.Ceil(), tc.ceil; got != want {
|
||||
t.Errorf("tc.x=%v: Ceil: got %v, want %v", tc.x, got, want)
|
||||
}
|
||||
if got, want := x.Mul(one), x; got != want {
|
||||
t.Errorf("tc.x=%v: Mul by one: got %v, want %v", tc.x, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var mulTestCases = []struct {
|
||||
x float64
|
||||
y float64
|
||||
z26_6 float64 // Equals truncate26_6(x)*truncate26_6(y).
|
||||
z52_12 float64 // Equals truncate52_12(x)*truncate52_12(y).
|
||||
s26_6 string
|
||||
s52_12 string
|
||||
}{{
|
||||
x: 0,
|
||||
y: 1.5,
|
||||
z26_6: 0,
|
||||
z52_12: 0,
|
||||
s26_6: "0:00",
|
||||
s52_12: "0:0000",
|
||||
}, {
|
||||
x: +1.25,
|
||||
y: +4,
|
||||
z26_6: +5,
|
||||
z52_12: +5,
|
||||
s26_6: "5:00",
|
||||
s52_12: "5:0000",
|
||||
}, {
|
||||
x: +1.25,
|
||||
y: -4,
|
||||
z26_6: -5,
|
||||
z52_12: -5,
|
||||
s26_6: "-5:00",
|
||||
s52_12: "-5:0000",
|
||||
}, {
|
||||
x: -1.25,
|
||||
y: +4,
|
||||
z26_6: -5,
|
||||
z52_12: -5,
|
||||
s26_6: "-5:00",
|
||||
s52_12: "-5:0000",
|
||||
}, {
|
||||
x: -1.25,
|
||||
y: -4,
|
||||
z26_6: +5,
|
||||
z52_12: +5,
|
||||
s26_6: "5:00",
|
||||
s52_12: "5:0000",
|
||||
}, {
|
||||
x: 1.25,
|
||||
y: 1.5,
|
||||
z26_6: 1.875,
|
||||
z52_12: 1.875,
|
||||
s26_6: "1:56",
|
||||
s52_12: "1:3584",
|
||||
}, {
|
||||
x: 1234.5,
|
||||
y: -8888.875,
|
||||
z26_6: -10973316.1875,
|
||||
z52_12: -10973316.1875,
|
||||
s26_6: "-10973316:12",
|
||||
s52_12: "-10973316:0768",
|
||||
}, {
|
||||
x: 1.515625, // 1 + 33/64 = 97/64
|
||||
y: 1.531250, // 1 + 34/64 = 98/64
|
||||
z26_6: 2.32080078125, // 2 + 1314/4096 = 9506/4096
|
||||
z52_12: 2.32080078125, // 2 + 1314/4096 = 9506/4096
|
||||
s26_6: "2:21", // 2.32812500000, which is closer than 2:20 (in decimal, 2.3125)
|
||||
s52_12: "2:1314", // 2.32080078125
|
||||
}, {
|
||||
x: 0.500244140625, // 2049/4096, approximately 32/64
|
||||
y: 0.500732421875, // 2051/4096, approximately 32/64
|
||||
z26_6: 0.25, // 4194304/16777216, or 1024/4096
|
||||
z52_12: 0.2504884600639343, // 4202499/16777216
|
||||
s26_6: "0:16", // 0.25000000000
|
||||
s52_12: "0:1026", // 0.25048828125, which is closer than 0:1027 (in decimal, 0.250732421875)
|
||||
}, {
|
||||
x: 0.015625, // 1/64
|
||||
y: 0.000244140625, // 1/4096, approximately 0/64
|
||||
z26_6: 0.0, // 0
|
||||
z52_12: 0.000003814697265625, // 1/262144
|
||||
s26_6: "0:00", // 0
|
||||
s52_12: "0:0000", // 0, which is closer than 0:0001 (in decimal, 0.000244140625)
|
||||
}, {
|
||||
// Round the Int52_12 calculation down.
|
||||
x: 1.44140625, // 1 + 1808/4096 = 5904/4096, approximately 92/64
|
||||
y: 1.44140625, // 1 + 1808/4096 = 5904/4096, approximately 92/64
|
||||
z26_6: 2.06640625, // 2 + 272/4096 = 8464/4096
|
||||
z52_12: 2.0776519775390625, // 2 + 318/4096 + 256/16777216 = 34857216/16777216
|
||||
s26_6: "2:04", // 2.06250000000, which is closer than 2:05 (in decimal, 2.078125000000)
|
||||
s52_12: "2:0318", // 2.07763671875, which is closer than 2:0319 (in decimal, 2.077880859375)
|
||||
}, {
|
||||
// Round the Int52_12 calculation up.
|
||||
x: 1.44140625, // 1 + 1808/4096 = 5904/4096, approximately 92/64
|
||||
y: 1.441650390625, // 1 + 1809/4096 = 5905/4096, approximately 92/64
|
||||
z26_6: 2.06640625, // 2 + 272/4096 = 8464/4096
|
||||
z52_12: 2.0780038833618164, // 2 + 319/4096 + 2064/16777216 = 34863120/16777216
|
||||
s26_6: "2:04", // 2.06250000000, which is closer than 2:05 (in decimal, 2.078125000000)
|
||||
s52_12: "2:0320", // 2.07812500000, which is closer than 2:0319 (in decimal, 2.077880859375)
|
||||
}}
|
||||
|
||||
func TestInt26_6Mul(t *testing.T) {
|
||||
for _, tc := range mulTestCases {
|
||||
x := Int26_6(tc.x * (1 << 6))
|
||||
y := Int26_6(tc.y * (1 << 6))
|
||||
if z := float64(x) * float64(y) / (1 << 12); z != tc.z26_6 {
|
||||
t.Errorf("tc.x=%v, tc.y=%v: z: got %v, want %v", tc.x, tc.y, z, tc.z26_6)
|
||||
continue
|
||||
}
|
||||
if got, want := x.Mul(y).String(), tc.s26_6; got != want {
|
||||
t.Errorf("tc.x=%v: Mul: got %q, want %q", tc.x, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInt52_12Mul(t *testing.T) {
|
||||
for _, tc := range mulTestCases {
|
||||
x := Int52_12(tc.x * (1 << 12))
|
||||
y := Int52_12(tc.y * (1 << 12))
|
||||
if z := float64(x) * float64(y) / (1 << 24); z != tc.z52_12 {
|
||||
t.Errorf("tc.x=%v, tc.y=%v: z: got %v, want %v", tc.x, tc.y, z, tc.z52_12)
|
||||
continue
|
||||
}
|
||||
if got, want := x.Mul(y).String(), tc.s52_12; got != want {
|
||||
t.Errorf("tc.x=%v: Mul: got %q, want %q", tc.x, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInt26_6MulByOneMinusIota(t *testing.T) {
|
||||
const (
|
||||
totalBits = 32
|
||||
fracBits = 6
|
||||
|
||||
oneMinusIota = Int26_6(1<<fracBits) - 1
|
||||
oneMinusIotaF = float64(oneMinusIota) / (1 << fracBits)
|
||||
)
|
||||
|
||||
for _, neg := range []bool{false, true} {
|
||||
for i := uint(0); i < totalBits; i++ {
|
||||
x := Int26_6(1 << i)
|
||||
if neg {
|
||||
x = -x
|
||||
} else if i == totalBits-1 {
|
||||
// A signed int32 can't represent 1<<31.
|
||||
continue
|
||||
}
|
||||
|
||||
// want equals x * oneMinusIota, rounded to nearest.
|
||||
want := Int26_6(0)
|
||||
if -1<<fracBits < x && x < 1<<fracBits {
|
||||
// (x * oneMinusIota) isn't exactly representable as an
|
||||
// Int26_6. Calculate the rounded value using float64 math.
|
||||
xF := float64(x) / (1 << fracBits)
|
||||
wantF := xF * oneMinusIotaF * (1 << fracBits)
|
||||
want = Int26_6(math.Floor(wantF + 0.5))
|
||||
} else {
|
||||
// (x * oneMinusIota) is exactly representable.
|
||||
want = oneMinusIota << (i - fracBits)
|
||||
if neg {
|
||||
want = -want
|
||||
}
|
||||
}
|
||||
|
||||
if got := x.Mul(oneMinusIota); got != want {
|
||||
t.Errorf("neg=%t, i=%d, x=%v, Mul: got %v, want %v", neg, i, x, got, want)
|
||||
}
|
||||
if got := x.mul(oneMinusIota); got != want {
|
||||
t.Errorf("neg=%t, i=%d, x=%v, mul: got %v, want %v", neg, i, x, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInt52_12MulByOneMinusIota(t *testing.T) {
|
||||
const (
|
||||
totalBits = 64
|
||||
fracBits = 12
|
||||
|
||||
oneMinusIota = Int52_12(1<<fracBits) - 1
|
||||
oneMinusIotaF = float64(oneMinusIota) / (1 << fracBits)
|
||||
)
|
||||
|
||||
for _, neg := range []bool{false, true} {
|
||||
for i := uint(0); i < totalBits; i++ {
|
||||
x := Int52_12(1 << i)
|
||||
if neg {
|
||||
x = -x
|
||||
} else if i == totalBits-1 {
|
||||
// A signed int64 can't represent 1<<63.
|
||||
continue
|
||||
}
|
||||
|
||||
// want equals x * oneMinusIota, rounded to nearest.
|
||||
want := Int52_12(0)
|
||||
if -1<<fracBits < x && x < 1<<fracBits {
|
||||
// (x * oneMinusIota) isn't exactly representable as an
|
||||
// Int52_12. Calculate the rounded value using float64 math.
|
||||
xF := float64(x) / (1 << fracBits)
|
||||
wantF := xF * oneMinusIotaF * (1 << fracBits)
|
||||
want = Int52_12(math.Floor(wantF + 0.5))
|
||||
} else {
|
||||
// (x * oneMinusIota) is exactly representable.
|
||||
want = oneMinusIota << (i - fracBits)
|
||||
if neg {
|
||||
want = -want
|
||||
}
|
||||
}
|
||||
|
||||
if got := x.Mul(oneMinusIota); got != want {
|
||||
t.Errorf("neg=%t, i=%d, x=%v, Mul: got %v, want %v", neg, i, x, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInt26_6MulVsMul(t *testing.T) {
|
||||
rng := rand.New(rand.NewSource(1))
|
||||
for i := 0; i < 10000; i++ {
|
||||
u := Int26_6(rng.Uint32())
|
||||
v := Int26_6(rng.Uint32())
|
||||
Mul := u.Mul(v)
|
||||
mul := u.mul(v)
|
||||
if Mul != mul {
|
||||
t.Errorf("u=%#08x, v=%#08x: Mul=%#08x and mul=%#08x differ",
|
||||
uint32(u), uint32(v), uint32(Mul), uint32(mul))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMuli32(t *testing.T) {
|
||||
rng := rand.New(rand.NewSource(2))
|
||||
for i := 0; i < 10000; i++ {
|
||||
u := int32(rng.Uint32())
|
||||
v := int32(rng.Uint32())
|
||||
lo, hi := muli32(u, v)
|
||||
got := uint64(lo) | uint64(hi)<<32
|
||||
want := uint64(int64(u) * int64(v))
|
||||
if got != want {
|
||||
t.Errorf("u=%#08x, v=%#08x: got %#016x, want %#016x", uint32(u), uint32(v), got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMulu32(t *testing.T) {
|
||||
rng := rand.New(rand.NewSource(3))
|
||||
for i := 0; i < 10000; i++ {
|
||||
u := rng.Uint32()
|
||||
v := rng.Uint32()
|
||||
lo, hi := mulu32(u, v)
|
||||
got := uint64(lo) | uint64(hi)<<32
|
||||
want := uint64(u) * uint64(v)
|
||||
if got != want {
|
||||
t.Errorf("u=%#08x, v=%#08x: got %#016x, want %#016x", u, v, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mul (with a lower case 'm') is an alternative implementation of Int26_6.Mul
|
||||
// (with an upper case 'M'). It has the same structure as the Int52_12.Mul
|
||||
// implementation, but Int26_6.mul is easier to test since Go has built-in
|
||||
// 64-bit integers.
|
||||
func (x Int26_6) mul(y Int26_6) Int26_6 {
|
||||
const M, N = 26, 6
|
||||
lo, hi := muli32(int32(x), int32(y))
|
||||
ret := Int26_6(hi<<M | lo>>N)
|
||||
ret += Int26_6((lo >> (N - 1)) & 1) // Round to nearest, instead of rounding down.
|
||||
return ret
|
||||
}
|
||||
|
||||
// muli32 multiplies two int32 values, returning the 64-bit signed integer
|
||||
// result as two uint32 values.
|
||||
//
|
||||
// muli32 isn't used directly by this package, but it has the same structure as
|
||||
// muli64, and muli32 is easier to test since Go has built-in 64-bit integers.
|
||||
func muli32(u, v int32) (lo, hi uint32) {
|
||||
const (
|
||||
s = 16
|
||||
mask = 1<<s - 1
|
||||
)
|
||||
|
||||
u1 := uint32(u >> s)
|
||||
u0 := uint32(u & mask)
|
||||
v1 := uint32(v >> s)
|
||||
v0 := uint32(v & mask)
|
||||
|
||||
w0 := u0 * v0
|
||||
t := u1*v0 + w0>>s
|
||||
w1 := t & mask
|
||||
w2 := uint32(int32(t) >> s)
|
||||
w1 += u0 * v1
|
||||
return uint32(u) * uint32(v), u1*v1 + w2 + uint32(int32(w1)>>s)
|
||||
}
|
||||
|
||||
// mulu32 is like muli32, except that it multiplies unsigned instead of signed
|
||||
// values.
|
||||
//
|
||||
// This implementation comes from $GOROOT/src/runtime/softfloat64.go's mullu
|
||||
// function, which is in turn adapted from Hacker's Delight.
|
||||
//
|
||||
// mulu32 (and its corresponding test, TestMulu32) isn't used directly by this
|
||||
// package. It is provided in this test file as a reference point to compare
|
||||
// the muli32 (and TestMuli32) implementations against.
|
||||
func mulu32(u, v uint32) (lo, hi uint32) {
|
||||
const (
|
||||
s = 16
|
||||
mask = 1<<s - 1
|
||||
)
|
||||
|
||||
u0 := u & mask
|
||||
u1 := u >> s
|
||||
v0 := v & mask
|
||||
v1 := v >> s
|
||||
|
||||
w0 := u0 * v0
|
||||
t := u1*v0 + w0>>s
|
||||
w1 := t & mask
|
||||
w2 := t >> s
|
||||
w1 += u0 * v1
|
||||
return u * v, u1*v1 + w2 + w1>>s
|
||||
}
|
||||
|
||||
20
vendor/golang.org/x/image/riff/riff.go
сгенерированный
поставляемый
20
vendor/golang.org/x/image/riff/riff.go
сгенерированный
поставляемый
@@ -23,6 +23,7 @@ import (
|
||||
var (
|
||||
errMissingPaddingByte = errors.New("riff: missing padding byte")
|
||||
errMissingRIFFChunkHeader = errors.New("riff: missing RIFF chunk header")
|
||||
errListSubchunkTooLong = errors.New("riff: list subchunk too long")
|
||||
errShortChunkData = errors.New("riff: short chunk data")
|
||||
errShortChunkHeader = errors.New("riff: short chunk header")
|
||||
errStaleReader = errors.New("riff: stale reader")
|
||||
@@ -100,13 +101,23 @@ func (z *Reader) Next() (chunkID FourCC, chunkLen uint32, chunkData io.Reader, e
|
||||
|
||||
// Drain the rest of the previous chunk.
|
||||
if z.chunkLen != 0 {
|
||||
_, z.err = io.Copy(ioutil.Discard, z.chunkReader)
|
||||
want := z.chunkLen
|
||||
var got int64
|
||||
got, z.err = io.Copy(ioutil.Discard, z.chunkReader)
|
||||
if z.err == nil && uint32(got) != want {
|
||||
z.err = errShortChunkData
|
||||
}
|
||||
if z.err != nil {
|
||||
return FourCC{}, 0, nil, z.err
|
||||
}
|
||||
}
|
||||
z.chunkReader = nil
|
||||
if z.padded {
|
||||
if z.totalLen == 0 {
|
||||
z.err = errListSubchunkTooLong
|
||||
return FourCC{}, 0, nil, z.err
|
||||
}
|
||||
z.totalLen--
|
||||
_, z.err = io.ReadFull(z.r, z.buf[:1])
|
||||
if z.err != nil {
|
||||
if z.err == io.EOF {
|
||||
@@ -114,7 +125,6 @@ func (z *Reader) Next() (chunkID FourCC, chunkLen uint32, chunkData io.Reader, e
|
||||
}
|
||||
return FourCC{}, 0, nil, z.err
|
||||
}
|
||||
z.totalLen--
|
||||
}
|
||||
|
||||
// We are done if we have no more data.
|
||||
@@ -129,7 +139,7 @@ func (z *Reader) Next() (chunkID FourCC, chunkLen uint32, chunkData io.Reader, e
|
||||
return FourCC{}, 0, nil, z.err
|
||||
}
|
||||
z.totalLen -= chunkHeaderSize
|
||||
if _, err = io.ReadFull(z.r, z.buf[:chunkHeaderSize]); err != nil {
|
||||
if _, z.err = io.ReadFull(z.r, z.buf[:chunkHeaderSize]); z.err != nil {
|
||||
if z.err == io.EOF || z.err == io.ErrUnexpectedEOF {
|
||||
z.err = errShortChunkHeader
|
||||
}
|
||||
@@ -137,6 +147,10 @@ func (z *Reader) Next() (chunkID FourCC, chunkLen uint32, chunkData io.Reader, e
|
||||
}
|
||||
chunkID = FourCC{z.buf[0], z.buf[1], z.buf[2], z.buf[3]}
|
||||
z.chunkLen = u32(z.buf[4:])
|
||||
if z.chunkLen > z.totalLen {
|
||||
z.err = errListSubchunkTooLong
|
||||
return FourCC{}, 0, nil, z.err
|
||||
}
|
||||
z.padded = z.chunkLen&1 == 1
|
||||
z.chunkReader = &chunkReader{z}
|
||||
return chunkID, z.chunkLen, z.chunkReader, nil
|
||||
|
||||
69
vendor/golang.org/x/image/riff/riff_test.go
сгенерированный
поставляемый
Обычный файл
69
vendor/golang.org/x/image/riff/riff_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,69 @@
|
||||
// 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 riff
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func encodeU32(u uint32) []byte {
|
||||
return []byte{
|
||||
byte(u >> 0),
|
||||
byte(u >> 8),
|
||||
byte(u >> 16),
|
||||
byte(u >> 24),
|
||||
}
|
||||
}
|
||||
|
||||
func TestShortChunks(t *testing.T) {
|
||||
// s is a RIFF(ABCD) with allegedly 256 bytes of data (excluding the
|
||||
// leading 8-byte "RIFF\x00\x01\x00\x00"). The first chunk of that ABCD
|
||||
// list is an abcd chunk of length m followed by n zeroes.
|
||||
for _, m := range []uint32{0, 8, 15, 200, 300} {
|
||||
for _, n := range []int{0, 1, 2, 7} {
|
||||
s := []byte("RIFF\x00\x01\x00\x00ABCDabcd")
|
||||
s = append(s, encodeU32(m)...)
|
||||
s = append(s, make([]byte, n)...)
|
||||
_, r, err := NewReader(bytes.NewReader(s))
|
||||
if err != nil {
|
||||
t.Errorf("m=%d, n=%d: NewReader: %v", m, n, err)
|
||||
continue
|
||||
}
|
||||
|
||||
_, _, _, err0 := r.Next()
|
||||
// The total "ABCD" list length is 256 bytes, of which the first 12
|
||||
// bytes are "ABCDabcd" plus the 4-byte encoding of m. If the
|
||||
// "abcd" subchunk length (m) plus those 12 bytes is greater than
|
||||
// the total list length, we have an invalid RIFF, and we expect an
|
||||
// errListSubchunkTooLong error.
|
||||
if m+12 > 256 {
|
||||
if err0 != errListSubchunkTooLong {
|
||||
t.Errorf("m=%d, n=%d: Next #0: got %v, want %v", m, n, err0, errListSubchunkTooLong)
|
||||
}
|
||||
continue
|
||||
}
|
||||
// Otherwise, we expect a nil error.
|
||||
if err0 != nil {
|
||||
t.Errorf("m=%d, n=%d: Next #0: %v", m, n, err0)
|
||||
continue
|
||||
}
|
||||
|
||||
_, _, _, err1 := r.Next()
|
||||
// If m > 0, then m > n, so that "abcd" subchunk doesn't have m
|
||||
// bytes of data. If m == 0, then that "abcd" subchunk is OK in
|
||||
// that it has 0 extra bytes of data, but the next subchunk (8 byte
|
||||
// header plus body) is missing, as we only have n < 8 more bytes.
|
||||
want := errShortChunkData
|
||||
if m == 0 {
|
||||
want = errShortChunkHeader
|
||||
}
|
||||
if err1 != want {
|
||||
t.Errorf("m=%d, n=%d: Next #1: got %v, want %v", m, n, err1, want)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
153
vendor/golang.org/x/image/vector/raster_floating.go
сгенерированный
поставляемый
Обычный файл
153
vendor/golang.org/x/image/vector/raster_floating.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,153 @@
|
||||
// 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 vector
|
||||
|
||||
// This file contains a floating point math implementation of the vector
|
||||
// graphics rasterizer.
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"golang.org/x/image/math/f32"
|
||||
)
|
||||
|
||||
func floatingMax(x, y float32) float32 {
|
||||
if x > y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
func floatingMin(x, y float32) float32 {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
func floatingFloor(x float32) int32 { return int32(math.Floor(float64(x))) }
|
||||
func floatingCeil(x float32) int32 { return int32(math.Ceil(float64(x))) }
|
||||
|
||||
func (z *Rasterizer) floatingLineTo(b f32.Vec2) {
|
||||
a := z.pen
|
||||
z.pen = b
|
||||
dir := float32(1)
|
||||
if a[1] > b[1] {
|
||||
dir, a, b = -1, b, a
|
||||
}
|
||||
// Horizontal line segments yield no change in coverage. Almost horizontal
|
||||
// segments would yield some change, in ideal math, but the computation
|
||||
// further below, involving 1 / (b[1] - a[1]), is unstable in floating
|
||||
// point math, so we treat the segment as if it was perfectly horizontal.
|
||||
if b[1]-a[1] <= 0.000001 {
|
||||
return
|
||||
}
|
||||
dxdy := (b[0] - a[0]) / (b[1] - a[1])
|
||||
|
||||
x := a[0]
|
||||
y := floatingFloor(a[1])
|
||||
yMax := floatingCeil(b[1])
|
||||
if yMax > int32(z.size.Y) {
|
||||
yMax = int32(z.size.Y)
|
||||
}
|
||||
width := int32(z.size.X)
|
||||
|
||||
for ; y < yMax; y++ {
|
||||
dy := floatingMin(float32(y+1), b[1]) - floatingMax(float32(y), a[1])
|
||||
xNext := x + dy*dxdy
|
||||
if y < 0 {
|
||||
x = xNext
|
||||
continue
|
||||
}
|
||||
buf := z.area[y*width:]
|
||||
d := dy * dir
|
||||
x0, x1 := x, xNext
|
||||
if x > xNext {
|
||||
x0, x1 = x1, x0
|
||||
}
|
||||
x0i := floatingFloor(x0)
|
||||
x0Floor := float32(x0i)
|
||||
x1i := floatingCeil(x1)
|
||||
x1Ceil := float32(x1i)
|
||||
|
||||
if x1i <= x0i+1 {
|
||||
xmf := 0.5*(x+xNext) - x0Floor
|
||||
if i := clamp(x0i+0, width); i < uint(len(buf)) {
|
||||
buf[i] += d - d*xmf
|
||||
}
|
||||
if i := clamp(x0i+1, width); i < uint(len(buf)) {
|
||||
buf[i] += d * xmf
|
||||
}
|
||||
} else {
|
||||
s := 1 / (x1 - x0)
|
||||
x0f := x0 - x0Floor
|
||||
oneMinusX0f := 1 - x0f
|
||||
a0 := 0.5 * s * oneMinusX0f * oneMinusX0f
|
||||
x1f := x1 - x1Ceil + 1
|
||||
am := 0.5 * s * x1f * x1f
|
||||
|
||||
if i := clamp(x0i, width); i < uint(len(buf)) {
|
||||
buf[i] += d * a0
|
||||
}
|
||||
|
||||
if x1i == x0i+2 {
|
||||
if i := clamp(x0i+1, width); i < uint(len(buf)) {
|
||||
buf[i] += d * (1 - a0 - am)
|
||||
}
|
||||
} else {
|
||||
a1 := s * (1.5 - x0f)
|
||||
if i := clamp(x0i+1, width); i < uint(len(buf)) {
|
||||
buf[i] += d * (a1 - a0)
|
||||
}
|
||||
dTimesS := d * s
|
||||
for xi := x0i + 2; xi < x1i-1; xi++ {
|
||||
if i := clamp(xi, width); i < uint(len(buf)) {
|
||||
buf[i] += dTimesS
|
||||
}
|
||||
}
|
||||
a2 := a1 + s*float32(x1i-x0i-3)
|
||||
if i := clamp(x1i-1, width); i < uint(len(buf)) {
|
||||
buf[i] += d * (1 - a2 - am)
|
||||
}
|
||||
}
|
||||
|
||||
if i := clamp(x1i, width); i < uint(len(buf)) {
|
||||
buf[i] += d * am
|
||||
}
|
||||
}
|
||||
|
||||
x = xNext
|
||||
}
|
||||
}
|
||||
|
||||
func floatingAccumulate(dst []uint8, src []float32) {
|
||||
// almost256 scales a floating point value in the range [0, 1] to a uint8
|
||||
// value in the range [0x00, 0xff].
|
||||
//
|
||||
// 255 is too small. Floating point math accumulates rounding errors, so a
|
||||
// fully covered src value that would in ideal math be float32(1) might be
|
||||
// float32(1-ε), and uint8(255 * (1-ε)) would be 0xfe instead of 0xff. The
|
||||
// uint8 conversion rounds to zero, not to nearest.
|
||||
//
|
||||
// 256 is too big. If we multiplied by 256, below, then a fully covered src
|
||||
// value of float32(1) would translate to uint8(256 * 1), which can be 0x00
|
||||
// instead of the maximal value 0xff.
|
||||
//
|
||||
// math.Float32bits(almost256) is 0x437fffff.
|
||||
const almost256 = 255.99998
|
||||
|
||||
acc := float32(0)
|
||||
for i, v := range src {
|
||||
acc += v
|
||||
a := acc
|
||||
if a < 0 {
|
||||
a = -a
|
||||
}
|
||||
if a > 1 {
|
||||
a = 1
|
||||
}
|
||||
dst[i] = uint8(almost256 * a)
|
||||
}
|
||||
}
|
||||
228
vendor/golang.org/x/image/vector/vector.go
сгенерированный
поставляемый
Обычный файл
228
vendor/golang.org/x/image/vector/vector.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,228 @@
|
||||
// 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 vector provides a rasterizer for 2-D vector graphics.
|
||||
package vector // import "golang.org/x/image/vector"
|
||||
|
||||
// The rasterizer's design follows
|
||||
// https://medium.com/@raphlinus/inside-the-fastest-font-renderer-in-the-world-75ae5270c445
|
||||
//
|
||||
// Proof of concept code is in
|
||||
// https://github.com/google/font-go
|
||||
//
|
||||
// See also:
|
||||
// http://nothings.org/gamedev/rasterize/
|
||||
// http://projects.tuxee.net/cl-vectors/section-the-cl-aa-algorithm
|
||||
// https://people.gnome.org/~mathieu/libart/internals.html#INTERNALS-SCANLINE
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/draw"
|
||||
"math"
|
||||
|
||||
"golang.org/x/image/math/f32"
|
||||
)
|
||||
|
||||
func midPoint(p, q f32.Vec2) f32.Vec2 {
|
||||
return f32.Vec2{
|
||||
(p[0] + q[0]) * 0.5,
|
||||
(p[1] + q[1]) * 0.5,
|
||||
}
|
||||
}
|
||||
|
||||
func lerp(t float32, p, q f32.Vec2) f32.Vec2 {
|
||||
return f32.Vec2{
|
||||
p[0] + t*(q[0]-p[0]),
|
||||
p[1] + t*(q[1]-p[1]),
|
||||
}
|
||||
}
|
||||
|
||||
func clamp(i, width int32) uint {
|
||||
if i < 0 {
|
||||
return 0
|
||||
}
|
||||
if i < width {
|
||||
return uint(i)
|
||||
}
|
||||
return uint(width)
|
||||
}
|
||||
|
||||
// NewRasterizer returns a new Rasterizer whose rendered mask image is bounded
|
||||
// by the given width and height.
|
||||
func NewRasterizer(w, h int) *Rasterizer {
|
||||
return &Rasterizer{
|
||||
area: make([]float32, w*h),
|
||||
size: image.Point{w, h},
|
||||
}
|
||||
}
|
||||
|
||||
// Raster is a 2-D vector graphics rasterizer.
|
||||
type Rasterizer struct {
|
||||
area []float32
|
||||
size image.Point
|
||||
first f32.Vec2
|
||||
pen f32.Vec2
|
||||
|
||||
// DrawOp is the operator used for the Draw method.
|
||||
//
|
||||
// The zero value is draw.Over.
|
||||
DrawOp draw.Op
|
||||
|
||||
// TODO: an exported field equivalent to the mask point in the
|
||||
// draw.DrawMask function in the stdlib image/draw package?
|
||||
}
|
||||
|
||||
// Reset resets a Rasterizer as if it was just returned by NewRasterizer.
|
||||
//
|
||||
// This includes setting z.DrawOp to draw.Over.
|
||||
func (z *Rasterizer) Reset(w, h int) {
|
||||
if n := w * h; n > cap(z.area) {
|
||||
z.area = make([]float32, n)
|
||||
} else {
|
||||
z.area = z.area[:n]
|
||||
for i := range z.area {
|
||||
z.area[i] = 0
|
||||
}
|
||||
}
|
||||
z.size = image.Point{w, h}
|
||||
z.first = f32.Vec2{}
|
||||
z.pen = f32.Vec2{}
|
||||
z.DrawOp = draw.Over
|
||||
}
|
||||
|
||||
// Size returns the width and height passed to NewRasterizer or Reset.
|
||||
func (z *Rasterizer) Size() image.Point {
|
||||
return z.size
|
||||
}
|
||||
|
||||
// Bounds returns the rectangle from (0, 0) to the width and height passed to
|
||||
// NewRasterizer or Reset.
|
||||
func (z *Rasterizer) Bounds() image.Rectangle {
|
||||
return image.Rectangle{Max: z.size}
|
||||
}
|
||||
|
||||
// Pen returns the location of the path-drawing pen: the last argument to the
|
||||
// most recent XxxTo call.
|
||||
func (z *Rasterizer) Pen() f32.Vec2 {
|
||||
return z.pen
|
||||
}
|
||||
|
||||
// ClosePath closes the current path.
|
||||
func (z *Rasterizer) ClosePath() {
|
||||
z.LineTo(z.first)
|
||||
}
|
||||
|
||||
// MoveTo starts a new path and moves the pen to a.
|
||||
//
|
||||
// The coordinates are allowed to be out of the Rasterizer's bounds.
|
||||
func (z *Rasterizer) MoveTo(a f32.Vec2) {
|
||||
z.first = a
|
||||
z.pen = a
|
||||
}
|
||||
|
||||
// LineTo adds a line segment, from the pen to b, and moves the pen to b.
|
||||
//
|
||||
// The coordinates are allowed to be out of the Rasterizer's bounds.
|
||||
func (z *Rasterizer) LineTo(b f32.Vec2) {
|
||||
// TODO: add a fixed point math implementation.
|
||||
z.floatingLineTo(b)
|
||||
}
|
||||
|
||||
// QuadTo adds a quadratic Bézier segment, from the pen via b to c, and moves
|
||||
// the pen to c.
|
||||
//
|
||||
// The coordinates are allowed to be out of the Rasterizer's bounds.
|
||||
func (z *Rasterizer) QuadTo(b, c f32.Vec2) {
|
||||
a := z.pen
|
||||
devsq := devSquared(a, b, c)
|
||||
if devsq >= 0.333 {
|
||||
const tol = 3
|
||||
n := 1 + int(math.Sqrt(math.Sqrt(tol*float64(devsq))))
|
||||
t, nInv := float32(0), 1/float32(n)
|
||||
for i := 0; i < n-1; i++ {
|
||||
t += nInv
|
||||
ab := lerp(t, a, b)
|
||||
bc := lerp(t, b, c)
|
||||
z.LineTo(lerp(t, ab, bc))
|
||||
}
|
||||
}
|
||||
z.LineTo(c)
|
||||
}
|
||||
|
||||
// CubeTo adds a cubic Bézier segment, from the pen via b and c to d, and moves
|
||||
// the pen to d.
|
||||
//
|
||||
// The coordinates are allowed to be out of the Rasterizer's bounds.
|
||||
func (z *Rasterizer) CubeTo(b, c, d f32.Vec2) {
|
||||
a := z.pen
|
||||
devsq := devSquared(a, b, d)
|
||||
if devsqAlt := devSquared(a, c, d); devsq < devsqAlt {
|
||||
devsq = devsqAlt
|
||||
}
|
||||
if devsq >= 0.333 {
|
||||
const tol = 3
|
||||
n := 1 + int(math.Sqrt(math.Sqrt(tol*float64(devsq))))
|
||||
t, nInv := float32(0), 1/float32(n)
|
||||
for i := 0; i < n-1; i++ {
|
||||
t += nInv
|
||||
ab := lerp(t, a, b)
|
||||
bc := lerp(t, b, c)
|
||||
cd := lerp(t, c, d)
|
||||
abc := lerp(t, ab, bc)
|
||||
bcd := lerp(t, bc, cd)
|
||||
z.LineTo(lerp(t, abc, bcd))
|
||||
}
|
||||
}
|
||||
z.LineTo(d)
|
||||
}
|
||||
|
||||
// devSquared returns a measure of how curvy the sequnce a to b to c is. It
|
||||
// determines how many line segments will approximate a Bézier curve segment.
|
||||
//
|
||||
// http://lists.nongnu.org/archive/html/freetype-devel/2016-08/msg00080.html
|
||||
// gives the rationale for this evenly spaced heuristic instead of a recursive
|
||||
// de Casteljau approach:
|
||||
//
|
||||
// The reason for the subdivision by n is that I expect the "flatness"
|
||||
// computation to be semi-expensive (it's done once rather than on each
|
||||
// potential subdivision) and also because you'll often get fewer subdivisions.
|
||||
// Taking a circular arc as a simplifying assumption (ie a spherical cow),
|
||||
// where I get n, a recursive approach would get 2^⌈lg n⌉, which, if I haven't
|
||||
// made any horrible mistakes, is expected to be 33% more in the limit.
|
||||
func devSquared(a, b, c f32.Vec2) float32 {
|
||||
devx := a[0] - 2*b[0] + c[0]
|
||||
devy := a[1] - 2*b[1] + c[1]
|
||||
return devx*devx + devy*devy
|
||||
}
|
||||
|
||||
// Draw implements the Drawer interface from the standard library's image/draw
|
||||
// package.
|
||||
//
|
||||
// The vector paths previously added via the XxxTo calls become the mask for
|
||||
// drawing src onto dst.
|
||||
func (z *Rasterizer) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point) {
|
||||
if src, ok := src.(*image.Uniform); ok {
|
||||
_, _, _, srcA := src.RGBA()
|
||||
switch dst := dst.(type) {
|
||||
case *image.Alpha:
|
||||
// Fast path for glyph rendering.
|
||||
if srcA == 0xffff && z.DrawOp == draw.Src {
|
||||
z.rasterizeDstAlphaSrcOpaqueOpSrc(dst, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
println("TODO: the general case")
|
||||
}
|
||||
|
||||
func (z *Rasterizer) rasterizeDstAlphaSrcOpaqueOpSrc(dst *image.Alpha, r image.Rectangle) {
|
||||
// TODO: add SIMD implementations.
|
||||
// TODO: add a fixed point math implementation.
|
||||
// TODO: non-zero vs even-odd winding?
|
||||
if r == dst.Bounds() && r == z.Bounds() {
|
||||
floatingAccumulate(dst.Pix, z.area)
|
||||
return
|
||||
}
|
||||
println("TODO: the general case")
|
||||
}
|
||||
76
vendor/golang.org/x/image/vector/vector_test.go
сгенерированный
поставляемый
Обычный файл
76
vendor/golang.org/x/image/vector/vector_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,76 @@
|
||||
// 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 vector
|
||||
|
||||
// TODO: add tests for NaN and Inf coordinates.
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/draw"
|
||||
"image/png"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/image/math/f32"
|
||||
)
|
||||
|
||||
// encodePNG is useful for manually debugging the tests.
|
||||
func encodePNG(dstFilename string, src image.Image) error {
|
||||
f, err := os.Create(dstFilename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
encErr := png.Encode(f, src)
|
||||
closeErr := f.Close()
|
||||
if encErr != nil {
|
||||
return encErr
|
||||
}
|
||||
return closeErr
|
||||
}
|
||||
|
||||
func TestBasicPath(t *testing.T) {
|
||||
want := []byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xaa, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x5f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x24, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa1, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x14, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4a, 0x00, 0x00,
|
||||
0x00, 0x00, 0xcc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0x00, 0x00,
|
||||
0x00, 0x00, 0x66, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xe4, 0xff, 0xff, 0xff, 0xb6, 0x00, 0x00,
|
||||
0x00, 0x00, 0x0c, 0xf2, 0xff, 0xff, 0xfe, 0x9e, 0x15, 0x00, 0x15, 0x96, 0xff, 0xce, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x88, 0xfc, 0xe3, 0x43, 0x00, 0x00, 0x00, 0x00, 0x06, 0xcd, 0xdc, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xde, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
||||
z := NewRasterizer(16, 16)
|
||||
z.MoveTo(f32.Vec2{2, 2})
|
||||
z.LineTo(f32.Vec2{8, 2})
|
||||
z.QuadTo(f32.Vec2{14, 2}, f32.Vec2{14, 14})
|
||||
z.CubeTo(f32.Vec2{8, 2}, f32.Vec2{5, 20}, f32.Vec2{2, 8})
|
||||
z.ClosePath()
|
||||
|
||||
dst := image.NewAlpha(z.Bounds())
|
||||
z.DrawOp = draw.Src
|
||||
z.Draw(dst, dst.Bounds(), image.Opaque, image.Point{})
|
||||
|
||||
got := dst.Pix
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("len(got)=%d and len(want)=%d differ", len(got), len(want))
|
||||
}
|
||||
for i := range got {
|
||||
delta := int(got[i]) - int(want[i])
|
||||
// The +/- 2 allows different implementations to give different
|
||||
// rounding errors.
|
||||
if delta < -2 || +2 < delta {
|
||||
t.Errorf("i=%d: got %#02x, want %#02x", i, got[i], want[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
8
vendor/golang.org/x/image/webp/decode.go
сгенерированный
поставляемый
8
vendor/golang.org/x/image/webp/decode.go
сгенерированный
поставляемый
@@ -2,11 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package webp implements a decoder for WEBP images.
|
||||
//
|
||||
// WEBP is defined at:
|
||||
// https://developers.google.com/speed/webp/docs/riff_container
|
||||
package webp // import "golang.org/x/image/webp"
|
||||
// +build go1.6
|
||||
|
||||
package webp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
2
vendor/golang.org/x/image/webp/decode_test.go
сгенерированный
поставляемый
2
vendor/golang.org/x/image/webp/decode_test.go
сгенерированный
поставляемый
@@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.6
|
||||
|
||||
package webp
|
||||
|
||||
import (
|
||||
|
||||
30
vendor/golang.org/x/image/webp/webp.go
сгенерированный
поставляемый
Обычный файл
30
vendor/golang.org/x/image/webp/webp.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,30 @@
|
||||
// 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 webp implements a decoder for WEBP images.
|
||||
//
|
||||
// WEBP is defined at:
|
||||
// https://developers.google.com/speed/webp/docs/riff_container
|
||||
//
|
||||
// It requires Go 1.6 or later.
|
||||
package webp // import "golang.org/x/image/webp"
|
||||
|
||||
// This blank Go file, other than the package clause, exists so that this
|
||||
// package can be built for Go 1.5 and earlier. (The other files in this
|
||||
// package are all marked "+build go1.6" for the NYCbCrA types introduced in Go
|
||||
// 1.6). There is no functionality in a blank package, but some image
|
||||
// manipulation programs might still underscore import this package for the
|
||||
// side effect of registering the WEBP format with the standard library's
|
||||
// image.RegisterFormat and image.Decode functions. For example, that program
|
||||
// might contain:
|
||||
//
|
||||
// // Underscore imports to register some formats for image.Decode.
|
||||
// import _ "image/gif"
|
||||
// import _ "image/jpeg"
|
||||
// import _ "image/png"
|
||||
// import _ "golang.org/x/image/webp"
|
||||
//
|
||||
// Such a program will still compile for Go 1.5 (due to this placeholder Go
|
||||
// file). It will simply not be able to recognize and decode WEBP (but still
|
||||
// handle GIF, JPEG and PNG).
|
||||
28
vendor/golang.org/x/sys/unix/asm_linux_s390x.s
сгенерированный
поставляемый
Обычный файл
28
vendor/golang.org/x/sys/unix/asm_linux_s390x.s
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,28 @@
|
||||
// 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.
|
||||
|
||||
// +build s390x
|
||||
// +build linux
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System calls for s390x, Linux
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
BR syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
BR syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
BR syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
BR syscall·RawSyscall6(SB)
|
||||
17
vendor/golang.org/x/sys/unix/mkall.sh
сгенерированный
поставляемый
17
vendor/golang.org/x/sys/unix/mkall.sh
сгенерированный
поставляемый
@@ -161,7 +161,7 @@ freebsd_arm)
|
||||
mkerrors="$mkerrors"
|
||||
mksyscall="./mksyscall.pl -l32 -arm"
|
||||
mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
|
||||
# Let the type of C char be singed for making the bare syscall
|
||||
# Let the type of C char be signed for making the bare syscall
|
||||
# API consistent across over platforms.
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||
;;
|
||||
@@ -194,7 +194,7 @@ linux_arm64)
|
||||
exit 1
|
||||
fi
|
||||
mksysnum="./mksysnum_linux.pl $unistd_h"
|
||||
# Let the type of C char be singed for making the bare syscall
|
||||
# Let the type of C char be signed for making the bare syscall
|
||||
# API consistent across over platforms.
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||
;;
|
||||
@@ -212,6 +212,17 @@ linux_ppc64le)
|
||||
mksysnum="./mksysnum_linux.pl $unistd_h"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
;;
|
||||
linux_s390x)
|
||||
GOOSARCH_in=syscall_linux_s390x.go
|
||||
unistd_h=/usr/include/asm/unistd.h
|
||||
mkerrors="$mkerrors -m64"
|
||||
mksysnum="./mksysnum_linux.pl $unistd_h"
|
||||
# Let the type of C char be signed to make the bare sys
|
||||
# API more consistent between platforms.
|
||||
# This is a deliberate departure from the way the syscall
|
||||
# package generates its version of the types file.
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||
;;
|
||||
netbsd_386)
|
||||
mkerrors="$mkerrors -m32"
|
||||
mksyscall="./mksyscall.pl -l32 -netbsd"
|
||||
@@ -269,6 +280,6 @@ esac
|
||||
if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
|
||||
if [ -n "$mktypes" ]; then
|
||||
echo "echo // +build $GOARCH,$GOOS > ztypes_$GOOSARCH.go";
|
||||
echo "$mktypes types_$GOOS.go | gofmt >>ztypes_$GOOSARCH.go";
|
||||
echo "$mktypes types_$GOOS.go | go run mkpost.go >>ztypes_$GOOSARCH.go";
|
||||
fi
|
||||
) | $run
|
||||
|
||||
62
vendor/golang.org/x/sys/unix/mkpost.go
сгенерированный
поставляемый
Обычный файл
62
vendor/golang.org/x/sys/unix/mkpost.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,62 @@
|
||||
// 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.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// mkpost processes the output of cgo -godefs to
|
||||
// modify the generated types. It is used to clean up
|
||||
// the sys API in an architecture specific manner.
|
||||
//
|
||||
// mkpost is run after cgo -godefs by mkall.sh.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
b, err := ioutil.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
s := string(b)
|
||||
|
||||
goarch := os.Getenv("GOARCH")
|
||||
goos := os.Getenv("GOOS")
|
||||
if goarch == "s390x" && goos == "linux" {
|
||||
// Export the types of PtraceRegs fields.
|
||||
re := regexp.MustCompile("ptrace(Psw|Fpregs|Per)")
|
||||
s = re.ReplaceAllString(s, "Ptrace$1")
|
||||
|
||||
// Replace padding fields inserted by cgo with blank identifiers.
|
||||
re = regexp.MustCompile("Pad_cgo[A-Za-z0-9_]*")
|
||||
s = re.ReplaceAllString(s, "_")
|
||||
|
||||
// Replace other unwanted fields with blank identifiers.
|
||||
re = regexp.MustCompile("X_[A-Za-z0-9_]*")
|
||||
s = re.ReplaceAllString(s, "_")
|
||||
|
||||
// Replace the control_regs union with a blank identifier for now.
|
||||
re = regexp.MustCompile("(Control_regs)\\s+\\[0\\]uint64")
|
||||
s = re.ReplaceAllString(s, "_ [0]uint64")
|
||||
}
|
||||
|
||||
// gofmt
|
||||
b, err = format.Source([]byte(s))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Append this command to the header to show where the new file
|
||||
// came from.
|
||||
re := regexp.MustCompile("(cgo -godefs [a-zA-Z0-9_]+\\.go.*)")
|
||||
b = re.ReplaceAll(b, []byte("$1 | go run mkpost.go"))
|
||||
|
||||
fmt.Printf("%s", b)
|
||||
}
|
||||
29
vendor/golang.org/x/sys/unix/syscall_bsd_test.go
сгенерированный
поставляемый
29
vendor/golang.org/x/sys/unix/syscall_bsd_test.go
сгенерированный
поставляемый
@@ -7,6 +7,7 @@
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
@@ -14,23 +15,37 @@ import (
|
||||
)
|
||||
|
||||
const MNT_WAIT = 1
|
||||
const MNT_NOWAIT = 2
|
||||
|
||||
func TestGetfsstat(t *testing.T) {
|
||||
n, err := unix.Getfsstat(nil, MNT_WAIT)
|
||||
const flags = MNT_NOWAIT // see golang.org/issue/16937
|
||||
n, err := unix.Getfsstat(nil, flags)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data := make([]unix.Statfs_t, n)
|
||||
n, err = unix.Getfsstat(data, MNT_WAIT)
|
||||
n2, err := unix.Getfsstat(data, flags)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
empty := unix.Statfs_t{}
|
||||
for _, stat := range data {
|
||||
if stat == empty {
|
||||
t.Fatal("an empty Statfs_t struct was returned")
|
||||
if n != n2 {
|
||||
t.Errorf("Getfsstat(nil) = %d, but subsequent Getfsstat(slice) = %d", n, n2)
|
||||
}
|
||||
for i, stat := range data {
|
||||
if stat == (unix.Statfs_t{}) {
|
||||
t.Errorf("index %v is an empty Statfs_t struct", i)
|
||||
}
|
||||
}
|
||||
if t.Failed() {
|
||||
for i, stat := range data[:n2] {
|
||||
t.Logf("data[%v] = %+v", i, stat)
|
||||
}
|
||||
mount, err := exec.Command("mount").CombinedOutput()
|
||||
if err != nil {
|
||||
t.Logf("mount: %v\n%s", err, mount)
|
||||
} else {
|
||||
t.Logf("mount: %s", mount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2
vendor/golang.org/x/sys/unix/syscall_darwin.go
сгенерированный
поставляемый
2
vendor/golang.org/x/sys/unix/syscall_darwin.go
сгенерированный
поставляемый
@@ -144,6 +144,7 @@ func getAttrList(path string, attrList attrList, attrBuf []byte, options uint) (
|
||||
uintptr(options),
|
||||
0,
|
||||
)
|
||||
use(unsafe.Pointer(_p0))
|
||||
if e1 != 0 {
|
||||
return nil, e1
|
||||
}
|
||||
@@ -196,6 +197,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
||||
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
|
||||
}
|
||||
r0, _, e1 := Syscall(SYS_GETFSSTAT64, uintptr(_p0), bufsize, uintptr(flags))
|
||||
use(unsafe.Pointer(_p0))
|
||||
n = int(r0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
|
||||
1
vendor/golang.org/x/sys/unix/syscall_dragonfly.go
сгенерированный
поставляемый
1
vendor/golang.org/x/sys/unix/syscall_dragonfly.go
сгенерированный
поставляемый
@@ -109,6 +109,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
||||
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
|
||||
}
|
||||
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
||||
use(unsafe.Pointer(_p0))
|
||||
n = int(r0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
|
||||
1
vendor/golang.org/x/sys/unix/syscall_freebsd.go
сгенерированный
поставляемый
1
vendor/golang.org/x/sys/unix/syscall_freebsd.go
сгенерированный
поставляемый
@@ -129,6 +129,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
||||
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
|
||||
}
|
||||
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
||||
use(unsafe.Pointer(_p0))
|
||||
n = int(r0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
|
||||
11
vendor/golang.org/x/sys/unix/syscall_linux.go
сгенерированный
поставляемый
11
vendor/golang.org/x/sys/unix/syscall_linux.go
сгенерированный
поставляемый
@@ -60,6 +60,15 @@ func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
|
||||
return openat(dirfd, path, flags|O_LARGEFILE, mode)
|
||||
}
|
||||
|
||||
//sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error)
|
||||
|
||||
func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return ppoll(nil, 0, timeout, sigmask)
|
||||
}
|
||||
return ppoll(&fds[0], len(fds), timeout, sigmask)
|
||||
}
|
||||
|
||||
//sys readlinkat(dirfd int, path string, buf []byte) (n int, err error)
|
||||
|
||||
func Readlink(path string, buf []byte) (n int, err error) {
|
||||
@@ -1043,8 +1052,6 @@ func Munmap(b []byte) (err error) {
|
||||
// Newfstatat
|
||||
// Nfsservctl
|
||||
// Personality
|
||||
// Poll
|
||||
// Ppoll
|
||||
// Pselect6
|
||||
// Ptrace
|
||||
// Putpmsg
|
||||
|
||||
9
vendor/golang.org/x/sys/unix/syscall_linux_386.go
сгенерированный
поставляемый
9
vendor/golang.org/x/sys/unix/syscall_linux_386.go
сгенерированный
поставляемый
@@ -388,3 +388,12 @@ func (msghdr *Msghdr) SetControllen(length int) {
|
||||
func (cmsg *Cmsghdr) SetLen(length int) {
|
||||
cmsg.Len = uint32(length)
|
||||
}
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
|
||||
9
vendor/golang.org/x/sys/unix/syscall_linux_amd64.go
сгенерированный
поставляемый
9
vendor/golang.org/x/sys/unix/syscall_linux_amd64.go
сгенерированный
поставляемый
@@ -146,3 +146,12 @@ func (msghdr *Msghdr) SetControllen(length int) {
|
||||
func (cmsg *Cmsghdr) SetLen(length int) {
|
||||
cmsg.Len = uint64(length)
|
||||
}
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
|
||||
9
vendor/golang.org/x/sys/unix/syscall_linux_arm.go
сгенерированный
поставляемый
9
vendor/golang.org/x/sys/unix/syscall_linux_arm.go
сгенерированный
поставляемый
@@ -252,3 +252,12 @@ func (msghdr *Msghdr) SetControllen(length int) {
|
||||
func (cmsg *Cmsghdr) SetLen(length int) {
|
||||
cmsg.Len = uint32(length)
|
||||
}
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
|
||||
12
vendor/golang.org/x/sys/unix/syscall_linux_arm64.go
сгенерированный
поставляемый
12
vendor/golang.org/x/sys/unix/syscall_linux_arm64.go
сгенерированный
поставляемый
@@ -178,3 +178,15 @@ const (
|
||||
SYS_EPOLL_CREATE = 1042
|
||||
SYS_EPOLL_WAIT = 1069
|
||||
)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
var ts *Timespec
|
||||
if timeout >= 0 {
|
||||
ts = new(Timespec)
|
||||
*ts = NsecToTimespec(int64(timeout) * 1e6)
|
||||
}
|
||||
if len(fds) == 0 {
|
||||
return ppoll(nil, 0, ts, nil)
|
||||
}
|
||||
return ppoll(&fds[0], len(fds), ts, nil)
|
||||
}
|
||||
|
||||
9
vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go
сгенерированный
поставляемый
9
vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go
сгенерированный
поставляемый
@@ -204,3 +204,12 @@ func (msghdr *Msghdr) SetControllen(length int) {
|
||||
func (cmsg *Cmsghdr) SetLen(length int) {
|
||||
cmsg.Len = uint64(length)
|
||||
}
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
|
||||
9
vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go
сгенерированный
поставляемый
9
vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go
сгенерированный
поставляемый
@@ -124,3 +124,12 @@ func Pipe2(p []int, flags int) (err error) {
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
|
||||
329
vendor/golang.org/x/sys/unix/syscall_linux_s390x.go
сгенерированный
поставляемый
Обычный файл
329
vendor/golang.org/x/sys/unix/syscall_linux_s390x.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,329 @@
|
||||
// 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.
|
||||
|
||||
// +build s390x,linux
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//sys Dup2(oldfd int, newfd int) (err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||
//sys Fstat(fd int, stat *Stat_t) (err error)
|
||||
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
|
||||
//sys Ftruncate(fd int, length int64) (err error)
|
||||
//sysnb Getegid() (egid int)
|
||||
//sysnb Geteuid() (euid int)
|
||||
//sysnb Getgid() (gid int)
|
||||
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error)
|
||||
//sysnb Getuid() (uid int)
|
||||
//sysnb InotifyInit() (fd int, err error)
|
||||
//sys Lchown(path string, uid int, gid int) (err error)
|
||||
//sys Lstat(path string, stat *Stat_t) (err error)
|
||||
//sys Pause() (err error)
|
||||
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
|
||||
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
|
||||
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
|
||||
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
|
||||
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
|
||||
//sys Setfsgid(gid int) (err error)
|
||||
//sys Setfsuid(uid int) (err error)
|
||||
//sysnb Setregid(rgid int, egid int) (err error)
|
||||
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
|
||||
//sysnb Setresuid(ruid int, euid int, suid int) (err error)
|
||||
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error)
|
||||
//sysnb Setreuid(ruid int, euid int) (err error)
|
||||
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
|
||||
//sys Stat(path string, stat *Stat_t) (err error)
|
||||
//sys Statfs(path string, buf *Statfs_t) (err error)
|
||||
//sys SyncFileRange(fd int, off int64, n int64, flags int) (err error)
|
||||
//sys Truncate(path string, length int64) (err error)
|
||||
//sysnb getgroups(n int, list *_Gid_t) (nn int, err error)
|
||||
//sysnb setgroups(n int, list *_Gid_t) (err error)
|
||||
|
||||
func Getpagesize() int { return 4096 }
|
||||
|
||||
//sysnb Gettimeofday(tv *Timeval) (err error)
|
||||
|
||||
func Time(t *Time_t) (tt Time_t, err error) {
|
||||
var tv Timeval
|
||||
err = Gettimeofday(&tv)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if t != nil {
|
||||
*t = Time_t(tv.Sec)
|
||||
}
|
||||
return Time_t(tv.Sec), nil
|
||||
}
|
||||
|
||||
//sys Utime(path string, buf *Utimbuf) (err error)
|
||||
|
||||
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
||||
|
||||
func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||
ts.Sec = nsec / 1e9
|
||||
ts.Nsec = nsec % 1e9
|
||||
return
|
||||
}
|
||||
|
||||
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||
nsec += 999 // round up to microsecond
|
||||
tv.Sec = nsec / 1e9
|
||||
tv.Usec = nsec % 1e9 / 1e3
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, 0) // pipe2 is the same as pipe when flags are set to 0.
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
func Pipe2(p []int, flags int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
func Ioperm(from int, num int, on int) (err error) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func Iopl(level int) (err error) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (r *PtraceRegs) PC() uint64 { return r.Psw.Addr }
|
||||
|
||||
func (r *PtraceRegs) SetPC(pc uint64) { r.Psw.Addr = pc }
|
||||
|
||||
func (iov *Iovec) SetLen(length int) {
|
||||
iov.Len = uint64(length)
|
||||
}
|
||||
|
||||
func (msghdr *Msghdr) SetControllen(length int) {
|
||||
msghdr.Controllen = uint64(length)
|
||||
}
|
||||
|
||||
func (cmsg *Cmsghdr) SetLen(length int) {
|
||||
cmsg.Len = uint64(length)
|
||||
}
|
||||
|
||||
// Linux on s390x uses the old mmap interface, which requires arguments to be passed in a struct.
|
||||
// mmap2 also requires arguments to be passed in a struct; it is currently not exposed in <asm/unistd.h>.
|
||||
func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
|
||||
mmap_args := [6]uintptr{addr, length, uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset)}
|
||||
r0, _, e1 := Syscall(SYS_MMAP, uintptr(unsafe.Pointer(&mmap_args[0])), 0, 0)
|
||||
use(unsafe.Pointer(&mmap_args[0]))
|
||||
xaddr = uintptr(r0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// On s390x Linux, all the socket calls go through an extra indirection.
|
||||
// The arguments to the underlying system call (SYS_SOCKETCALL) are the
|
||||
// number below and a pointer to an array of uintptr.
|
||||
const (
|
||||
// see linux/net.h
|
||||
netSocket = 1
|
||||
netBind = 2
|
||||
netConnect = 3
|
||||
netListen = 4
|
||||
netAccept = 5
|
||||
netGetSockName = 6
|
||||
netGetPeerName = 7
|
||||
netSocketPair = 8
|
||||
netSend = 9
|
||||
netRecv = 10
|
||||
netSendTo = 11
|
||||
netRecvFrom = 12
|
||||
netShutdown = 13
|
||||
netSetSockOpt = 14
|
||||
netGetSockOpt = 15
|
||||
netSendMsg = 16
|
||||
netRecvMsg = 17
|
||||
netAccept4 = 18
|
||||
netRecvMMsg = 19
|
||||
netSendMMsg = 20
|
||||
)
|
||||
|
||||
func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (int, error) {
|
||||
args := [3]uintptr{uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))}
|
||||
fd, _, err := Syscall(SYS_SOCKETCALL, netAccept, uintptr(unsafe.Pointer(&args)), 0)
|
||||
if err != 0 {
|
||||
return 0, err
|
||||
}
|
||||
return int(fd), nil
|
||||
}
|
||||
|
||||
func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (int, error) {
|
||||
args := [4]uintptr{uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags)}
|
||||
fd, _, err := Syscall(SYS_SOCKETCALL, netAccept4, uintptr(unsafe.Pointer(&args)), 0)
|
||||
if err != 0 {
|
||||
return 0, err
|
||||
}
|
||||
return int(fd), nil
|
||||
}
|
||||
|
||||
func getsockname(s int, rsa *RawSockaddrAny, addrlen *_Socklen) error {
|
||||
args := [3]uintptr{uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))}
|
||||
_, _, err := RawSyscall(SYS_SOCKETCALL, netGetSockName, uintptr(unsafe.Pointer(&args)), 0)
|
||||
if err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getpeername(s int, rsa *RawSockaddrAny, addrlen *_Socklen) error {
|
||||
args := [3]uintptr{uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))}
|
||||
_, _, err := RawSyscall(SYS_SOCKETCALL, netGetPeerName, uintptr(unsafe.Pointer(&args)), 0)
|
||||
if err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func socketpair(domain int, typ int, flags int, fd *[2]int32) error {
|
||||
args := [4]uintptr{uintptr(domain), uintptr(typ), uintptr(flags), uintptr(unsafe.Pointer(fd))}
|
||||
_, _, err := RawSyscall(SYS_SOCKETCALL, netSocketPair, uintptr(unsafe.Pointer(&args)), 0)
|
||||
if err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func bind(s int, addr unsafe.Pointer, addrlen _Socklen) error {
|
||||
args := [3]uintptr{uintptr(s), uintptr(addr), uintptr(addrlen)}
|
||||
_, _, err := Syscall(SYS_SOCKETCALL, netBind, uintptr(unsafe.Pointer(&args)), 0)
|
||||
if err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func connect(s int, addr unsafe.Pointer, addrlen _Socklen) error {
|
||||
args := [3]uintptr{uintptr(s), uintptr(addr), uintptr(addrlen)}
|
||||
_, _, err := Syscall(SYS_SOCKETCALL, netConnect, uintptr(unsafe.Pointer(&args)), 0)
|
||||
if err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func socket(domain int, typ int, proto int) (int, error) {
|
||||
args := [3]uintptr{uintptr(domain), uintptr(typ), uintptr(proto)}
|
||||
fd, _, err := RawSyscall(SYS_SOCKETCALL, netSocket, uintptr(unsafe.Pointer(&args)), 0)
|
||||
if err != 0 {
|
||||
return 0, err
|
||||
}
|
||||
return int(fd), nil
|
||||
}
|
||||
|
||||
func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) error {
|
||||
args := [5]uintptr{uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen))}
|
||||
_, _, err := Syscall(SYS_SOCKETCALL, netGetSockOpt, uintptr(unsafe.Pointer(&args)), 0)
|
||||
if err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) error {
|
||||
args := [4]uintptr{uintptr(s), uintptr(level), uintptr(name), uintptr(val)}
|
||||
_, _, err := Syscall(SYS_SOCKETCALL, netSetSockOpt, uintptr(unsafe.Pointer(&args)), 0)
|
||||
if err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func recvfrom(s int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (int, error) {
|
||||
var base uintptr
|
||||
if len(p) > 0 {
|
||||
base = uintptr(unsafe.Pointer(&p[0]))
|
||||
}
|
||||
args := [6]uintptr{uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))}
|
||||
n, _, err := Syscall(SYS_SOCKETCALL, netRecvFrom, uintptr(unsafe.Pointer(&args)), 0)
|
||||
if err != 0 {
|
||||
return 0, err
|
||||
}
|
||||
return int(n), nil
|
||||
}
|
||||
|
||||
func sendto(s int, p []byte, flags int, to unsafe.Pointer, addrlen _Socklen) error {
|
||||
var base uintptr
|
||||
if len(p) > 0 {
|
||||
base = uintptr(unsafe.Pointer(&p[0]))
|
||||
}
|
||||
args := [6]uintptr{uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(to), uintptr(addrlen)}
|
||||
_, _, err := Syscall(SYS_SOCKETCALL, netSendTo, uintptr(unsafe.Pointer(&args)), 0)
|
||||
if err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func recvmsg(s int, msg *Msghdr, flags int) (int, error) {
|
||||
args := [3]uintptr{uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)}
|
||||
n, _, err := Syscall(SYS_SOCKETCALL, netRecvMsg, uintptr(unsafe.Pointer(&args)), 0)
|
||||
if err != 0 {
|
||||
return 0, err
|
||||
}
|
||||
return int(n), nil
|
||||
}
|
||||
|
||||
func sendmsg(s int, msg *Msghdr, flags int) (int, error) {
|
||||
args := [3]uintptr{uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)}
|
||||
n, _, err := Syscall(SYS_SOCKETCALL, netSendMsg, uintptr(unsafe.Pointer(&args)), 0)
|
||||
if err != 0 {
|
||||
return 0, err
|
||||
}
|
||||
return int(n), nil
|
||||
}
|
||||
|
||||
func Listen(s int, n int) error {
|
||||
args := [2]uintptr{uintptr(s), uintptr(n)}
|
||||
_, _, err := Syscall(SYS_SOCKETCALL, netListen, uintptr(unsafe.Pointer(&args)), 0)
|
||||
if err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Shutdown(s, how int) error {
|
||||
args := [2]uintptr{uintptr(s), uintptr(how)}
|
||||
_, _, err := Syscall(SYS_SOCKETCALL, netShutdown, uintptr(unsafe.Pointer(&args)), 0)
|
||||
if err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
76
vendor/golang.org/x/sys/unix/syscall_linux_test.go
сгенерированный
поставляемый
76
vendor/golang.org/x/sys/unix/syscall_linux_test.go
сгенерированный
поставляемый
@@ -15,6 +15,82 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func TestPoll(t *testing.T) {
|
||||
f, cleanup := mktmpfifo(t)
|
||||
defer cleanup()
|
||||
|
||||
const timeout = 100
|
||||
|
||||
ok := make(chan bool, 1)
|
||||
go func() {
|
||||
select {
|
||||
case <-time.After(10 * timeout * time.Millisecond):
|
||||
t.Errorf("Poll: failed to timeout after %d milliseconds", 10*timeout)
|
||||
case <-ok:
|
||||
}
|
||||
}()
|
||||
|
||||
fds := []unix.PollFd{{Fd: int32(f.Fd()), Events: unix.POLLIN}}
|
||||
n, err := unix.Poll(fds, timeout)
|
||||
ok <- true
|
||||
if err != nil {
|
||||
t.Errorf("Poll: unexpected error: %v", err)
|
||||
return
|
||||
}
|
||||
if n != 0 {
|
||||
t.Errorf("Poll: wrong number of events: got %v, expected %v", n, 0)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestPpoll(t *testing.T) {
|
||||
f, cleanup := mktmpfifo(t)
|
||||
defer cleanup()
|
||||
|
||||
const timeout = 100 * time.Millisecond
|
||||
|
||||
ok := make(chan bool, 1)
|
||||
go func() {
|
||||
select {
|
||||
case <-time.After(10 * timeout):
|
||||
t.Errorf("Ppoll: failed to timeout after %d", 10*timeout)
|
||||
case <-ok:
|
||||
}
|
||||
}()
|
||||
|
||||
fds := []unix.PollFd{{Fd: int32(f.Fd()), Events: unix.POLLIN}}
|
||||
timeoutTs := unix.NsecToTimespec(int64(timeout))
|
||||
n, err := unix.Ppoll(fds, &timeoutTs, nil)
|
||||
ok <- true
|
||||
if err != nil {
|
||||
t.Errorf("Ppoll: unexpected error: %v", err)
|
||||
return
|
||||
}
|
||||
if n != 0 {
|
||||
t.Errorf("Ppoll: wrong number of events: got %v, expected %v", n, 0)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// mktmpfifo creates a temporary FIFO and provides a cleanup function.
|
||||
func mktmpfifo(t *testing.T) (*os.File, func()) {
|
||||
err := unix.Mkfifo("fifo", 0666)
|
||||
if err != nil {
|
||||
t.Fatalf("mktmpfifo: failed to create FIFO: %v", err)
|
||||
}
|
||||
|
||||
f, err := os.OpenFile("fifo", os.O_RDWR, 0666)
|
||||
if err != nil {
|
||||
os.Remove("fifo")
|
||||
t.Fatalf("mktmpfifo: failed to open FIFO: %v", err)
|
||||
}
|
||||
|
||||
return f, func() {
|
||||
f.Close()
|
||||
os.Remove("fifo")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTime(t *testing.T) {
|
||||
var ut unix.Time_t
|
||||
ut2, err := unix.Time(&ut)
|
||||
|
||||
1
vendor/golang.org/x/sys/unix/syscall_openbsd.go
сгенерированный
поставляемый
1
vendor/golang.org/x/sys/unix/syscall_openbsd.go
сгенерированный
поставляемый
@@ -111,6 +111,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
||||
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
|
||||
}
|
||||
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
||||
use(unsafe.Pointer(_p0))
|
||||
n = int(r0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
|
||||
46
vendor/golang.org/x/sys/unix/syscall_solaris.go
сгенерированный
поставляемый
46
vendor/golang.org/x/sys/unix/syscall_solaris.go
сгенерированный
поставляемый
@@ -72,18 +72,20 @@ func ParseDirent(buf []byte, max int, names []string) (consumed int, count int,
|
||||
return origlen - len(buf), count, names
|
||||
}
|
||||
|
||||
func pipe() (r uintptr, w uintptr, err uintptr)
|
||||
//sysnb pipe(p *[2]_C_int) (n int, err error)
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
r0, w0, e1 := pipe()
|
||||
if e1 != 0 {
|
||||
err = syscall.Errno(e1)
|
||||
var pp [2]_C_int
|
||||
n, err := pipe(&pp)
|
||||
if n != 0 {
|
||||
return err
|
||||
}
|
||||
p[0], p[1] = int(r0), int(w0)
|
||||
return
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
@@ -269,24 +271,34 @@ func (w WaitStatus) StopSignal() syscall.Signal {
|
||||
|
||||
func (w WaitStatus) TrapCause() int { return -1 }
|
||||
|
||||
func wait4(pid uintptr, wstatus *WaitStatus, options uintptr, rusage *Rusage) (wpid uintptr, err uintptr)
|
||||
//sys wait4(pid int32, statusp *_C_int, options int, rusage *Rusage) (wpid int32, err error)
|
||||
|
||||
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
|
||||
r0, e1 := wait4(uintptr(pid), wstatus, uintptr(options), rusage)
|
||||
if e1 != 0 {
|
||||
err = syscall.Errno(e1)
|
||||
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (int, error) {
|
||||
var status _C_int
|
||||
rpid, err := wait4(int32(pid), &status, options, rusage)
|
||||
wpid := int(rpid)
|
||||
if wpid == -1 {
|
||||
return wpid, err
|
||||
}
|
||||
return int(r0), err
|
||||
if wstatus != nil {
|
||||
*wstatus = WaitStatus(status)
|
||||
}
|
||||
return wpid, nil
|
||||
}
|
||||
|
||||
func gethostname() (name string, err uintptr)
|
||||
//sys gethostname(buf []byte) (n int, err error)
|
||||
|
||||
func Gethostname() (name string, err error) {
|
||||
name, e1 := gethostname()
|
||||
if e1 != 0 {
|
||||
err = syscall.Errno(e1)
|
||||
var buf [MaxHostNameLen]byte
|
||||
n, err := gethostname(buf[:])
|
||||
if n != 0 {
|
||||
return "", err
|
||||
}
|
||||
return name, err
|
||||
n = clen(buf[:])
|
||||
if n < 1 {
|
||||
return "", EFAULT
|
||||
}
|
||||
return string(buf[:n]), nil
|
||||
}
|
||||
|
||||
//sys utimes(path string, times *[2]Timeval) (err error)
|
||||
|
||||
37
vendor/golang.org/x/sys/unix/types_linux.go
сгенерированный
поставляемый
37
vendor/golang.org/x/sys/unix/types_linux.go
сгенерированный
поставляемый
@@ -24,6 +24,7 @@ package unix
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netpacket/packet.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/epoll.h>
|
||||
@@ -102,10 +103,22 @@ typedef struct user_pt_regs PtraceRegs;
|
||||
typedef struct pt_regs PtraceRegs;
|
||||
#elif defined(__mips__)
|
||||
typedef struct user PtraceRegs;
|
||||
#elif defined(__s390x__)
|
||||
typedef struct _user_regs_struct PtraceRegs;
|
||||
#else
|
||||
typedef struct user_regs_struct PtraceRegs;
|
||||
#endif
|
||||
|
||||
#if defined(__s390x__)
|
||||
typedef struct _user_psw_struct ptracePsw;
|
||||
typedef struct _user_fpregs_struct ptraceFpregs;
|
||||
typedef struct _user_per_struct ptracePer;
|
||||
#else
|
||||
typedef struct {} ptracePsw;
|
||||
typedef struct {} ptraceFpregs;
|
||||
typedef struct {} ptracePer;
|
||||
#endif
|
||||
|
||||
// The real epoll_event is a union, and godefs doesn't handle it well.
|
||||
struct my_epoll_event {
|
||||
uint32_t events;
|
||||
@@ -113,8 +126,7 @@ struct my_epoll_event {
|
||||
// padding is not specified in linux/eventpoll.h but added to conform to the
|
||||
// alignment requirements of EABI
|
||||
int32_t padFd;
|
||||
#endif
|
||||
#ifdef __powerpc64__
|
||||
#elif defined(__powerpc64__) || defined(__s390x__)
|
||||
int32_t _padFd;
|
||||
#endif
|
||||
int32_t fd;
|
||||
@@ -393,6 +405,13 @@ const SizeofInotifyEvent = C.sizeof_struct_inotify_event
|
||||
// Register structures
|
||||
type PtraceRegs C.PtraceRegs
|
||||
|
||||
// Structures contained in PtraceRegs on s390x (exported by mkpost.go)
|
||||
type ptracePsw C.ptracePsw
|
||||
|
||||
type ptraceFpregs C.ptraceFpregs
|
||||
|
||||
type ptracePer C.ptracePer
|
||||
|
||||
// Misc
|
||||
|
||||
type FdSet C.fd_set
|
||||
@@ -412,6 +431,20 @@ const (
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLIN = C.POLLIN
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLRDHUP = C.POLLRDHUP
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLNVAL = C.POLLNVAL
|
||||
)
|
||||
|
||||
type Sigset_t C.sigset_t
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.termios_t
|
||||
|
||||
2
vendor/golang.org/x/sys/unix/types_solaris.go
сгенерированный
поставляемый
2
vendor/golang.org/x/sys/unix/types_solaris.go
сгенерированный
поставляемый
@@ -22,6 +22,7 @@ package unix
|
||||
#define __USE_LEGACY_PROTOTYPES__ // iovec
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
@@ -81,6 +82,7 @@ const (
|
||||
sizeofLong = C.sizeof_long
|
||||
sizeofLongLong = C.sizeof_longlong
|
||||
PathMax = C.PATH_MAX
|
||||
MaxHostNameLen = C.MAXHOSTNAMELEN
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
1
vendor/golang.org/x/sys/unix/zerrors_linux_386.go
сгенерированный
поставляемый
1
vendor/golang.org/x/sys/unix/zerrors_linux_386.go
сгенерированный
поставляемый
@@ -216,6 +216,7 @@ const (
|
||||
CLONE_FILES = 0x400
|
||||
CLONE_FS = 0x200
|
||||
CLONE_IO = 0x80000000
|
||||
CLONE_NEWCGROUP = 0x2000000
|
||||
CLONE_NEWIPC = 0x8000000
|
||||
CLONE_NEWNET = 0x40000000
|
||||
CLONE_NEWNS = 0x20000
|
||||
|
||||
1
vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
сгенерированный
поставляемый
1
vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
сгенерированный
поставляемый
@@ -216,6 +216,7 @@ const (
|
||||
CLONE_FILES = 0x400
|
||||
CLONE_FS = 0x200
|
||||
CLONE_IO = 0x80000000
|
||||
CLONE_NEWCGROUP = 0x2000000
|
||||
CLONE_NEWIPC = 0x8000000
|
||||
CLONE_NEWNET = 0x40000000
|
||||
CLONE_NEWNS = 0x20000
|
||||
|
||||
1
vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
сгенерированный
поставляемый
1
vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
сгенерированный
поставляемый
@@ -212,6 +212,7 @@ const (
|
||||
CLONE_FILES = 0x400
|
||||
CLONE_FS = 0x200
|
||||
CLONE_IO = 0x80000000
|
||||
CLONE_NEWCGROUP = 0x2000000
|
||||
CLONE_NEWIPC = 0x8000000
|
||||
CLONE_NEWNET = 0x40000000
|
||||
CLONE_NEWNS = 0x20000
|
||||
|
||||
1
vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
сгенерированный
поставляемый
1
vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
сгенерированный
поставляемый
@@ -222,6 +222,7 @@ const (
|
||||
CLONE_FILES = 0x400
|
||||
CLONE_FS = 0x200
|
||||
CLONE_IO = 0x80000000
|
||||
CLONE_NEWCGROUP = 0x2000000
|
||||
CLONE_NEWIPC = 0x8000000
|
||||
CLONE_NEWNET = 0x40000000
|
||||
CLONE_NEWNS = 0x20000
|
||||
|
||||
1
vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
сгенерированный
поставляемый
1
vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
сгенерированный
поставляемый
@@ -221,6 +221,7 @@ const (
|
||||
CLONE_FILES = 0x400
|
||||
CLONE_FS = 0x200
|
||||
CLONE_IO = 0x80000000
|
||||
CLONE_NEWCGROUP = 0x2000000
|
||||
CLONE_NEWIPC = 0x8000000
|
||||
CLONE_NEWNET = 0x40000000
|
||||
CLONE_NEWNS = 0x20000
|
||||
|
||||
1
vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
сгенерированный
поставляемый
1
vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
сгенерированный
поставляемый
@@ -221,6 +221,7 @@ const (
|
||||
CLONE_FILES = 0x400
|
||||
CLONE_FS = 0x200
|
||||
CLONE_IO = 0x80000000
|
||||
CLONE_NEWCGROUP = 0x2000000
|
||||
CLONE_NEWIPC = 0x8000000
|
||||
CLONE_NEWNET = 0x40000000
|
||||
CLONE_NEWNS = 0x20000
|
||||
|
||||
1
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
сгенерированный
поставляемый
1
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
сгенерированный
поставляемый
@@ -223,6 +223,7 @@ const (
|
||||
CLONE_FILES = 0x400
|
||||
CLONE_FS = 0x200
|
||||
CLONE_IO = 0x80000000
|
||||
CLONE_NEWCGROUP = 0x2000000
|
||||
CLONE_NEWIPC = 0x8000000
|
||||
CLONE_NEWNET = 0x40000000
|
||||
CLONE_NEWNS = 0x20000
|
||||
|
||||
1
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
сгенерированный
поставляемый
1
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
сгенерированный
поставляемый
@@ -222,6 +222,7 @@ const (
|
||||
CLONE_FILES = 0x400
|
||||
CLONE_FS = 0x200
|
||||
CLONE_IO = 0x80000000
|
||||
CLONE_NEWCGROUP = 0x2000000
|
||||
CLONE_NEWIPC = 0x8000000
|
||||
CLONE_NEWNET = 0x40000000
|
||||
CLONE_NEWNS = 0x20000
|
||||
|
||||
2027
vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
сгенерированный
поставляемый
Обычный файл
2027
vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
сгенерированный
поставляемый
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
1
vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go
сгенерированный
поставляемый
1
vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go
сгенерированный
поставляемый
@@ -222,6 +222,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
|
||||
_p0 = unsafe.Pointer(&_zero)
|
||||
}
|
||||
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
|
||||
use(_p0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
|
||||
1
vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go
сгенерированный
поставляемый
1
vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go
сгенерированный
поставляемый
@@ -222,6 +222,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
|
||||
_p0 = unsafe.Pointer(&_zero)
|
||||
}
|
||||
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
|
||||
use(_p0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
|
||||
1
vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go
сгенерированный
поставляемый
1
vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go
сгенерированный
поставляемый
@@ -222,6 +222,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
|
||||
_p0 = unsafe.Pointer(&_zero)
|
||||
}
|
||||
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
|
||||
use(_p0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
|
||||
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Ссылка в новой задаче
Block a user