mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Migrate from U2F to Webauthn Co-authored-by: Andrew Thornton <art27@cantab.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
		
			
				
	
	
		
			439 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			439 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
package errors
 | 
						|
 | 
						|
import (
 | 
						|
	"crypto/x509"
 | 
						|
	"encoding/json"
 | 
						|
	"fmt"
 | 
						|
)
 | 
						|
 | 
						|
// Error is the error type usually returned by functions in CF SSL package.
 | 
						|
// It contains a 4-digit error code where the most significant digit
 | 
						|
// describes the category where the error occurred and the rest 3 digits
 | 
						|
// describe the specific error reason.
 | 
						|
type Error struct {
 | 
						|
	ErrorCode int    `json:"code"`
 | 
						|
	Message   string `json:"message"`
 | 
						|
}
 | 
						|
 | 
						|
// Category is the most significant digit of the error code.
 | 
						|
type Category int
 | 
						|
 | 
						|
// Reason is the last 3 digits of the error code.
 | 
						|
type Reason int
 | 
						|
 | 
						|
const (
 | 
						|
	// Success indicates no error occurred.
 | 
						|
	Success Category = 1000 * iota // 0XXX
 | 
						|
 | 
						|
	// CertificateError indicates a fault in a certificate.
 | 
						|
	CertificateError // 1XXX
 | 
						|
 | 
						|
	// PrivateKeyError indicates a fault in a private key.
 | 
						|
	PrivateKeyError // 2XXX
 | 
						|
 | 
						|
	// IntermediatesError indicates a fault in an intermediate.
 | 
						|
	IntermediatesError // 3XXX
 | 
						|
 | 
						|
	// RootError indicates a fault in a root.
 | 
						|
	RootError // 4XXX
 | 
						|
 | 
						|
	// PolicyError indicates an error arising from a malformed or
 | 
						|
	// non-existent policy, or a breach of policy.
 | 
						|
	PolicyError // 5XXX
 | 
						|
 | 
						|
	// DialError indicates a network fault.
 | 
						|
	DialError // 6XXX
 | 
						|
 | 
						|
	// APIClientError indicates a problem with the API client.
 | 
						|
	APIClientError // 7XXX
 | 
						|
 | 
						|
	// OCSPError indicates a problem with OCSP signing
 | 
						|
	OCSPError // 8XXX
 | 
						|
 | 
						|
	// CSRError indicates a problem with CSR parsing
 | 
						|
	CSRError // 9XXX
 | 
						|
 | 
						|
	// CTError indicates a problem with the certificate transparency process
 | 
						|
	CTError // 10XXX
 | 
						|
 | 
						|
	// CertStoreError indicates a problem with the certificate store
 | 
						|
	CertStoreError // 11XXX
 | 
						|
)
 | 
						|
 | 
						|
// None is a non-specified error.
 | 
						|
const (
 | 
						|
	None Reason = iota
 | 
						|
)
 | 
						|
 | 
						|
// Warning code for a success
 | 
						|
const (
 | 
						|
	BundleExpiringBit      int = 1 << iota // 0x01
 | 
						|
	BundleNotUbiquitousBit                 // 0x02
 | 
						|
)
 | 
						|
 | 
						|
// Parsing errors
 | 
						|
const (
 | 
						|
	Unknown      Reason = iota // X000
 | 
						|
	ReadFailed                 // X001
 | 
						|
	DecodeFailed               // X002
 | 
						|
	ParseFailed                // X003
 | 
						|
)
 | 
						|
 | 
						|
// The following represent certificate non-parsing errors, and must be
 | 
						|
// specified along with CertificateError.
 | 
						|
const (
 | 
						|
	// SelfSigned indicates that a certificate is self-signed and
 | 
						|
	// cannot be used in the manner being attempted.
 | 
						|
	SelfSigned Reason = 100 * (iota + 1) // Code 11XX
 | 
						|
 | 
						|
	// VerifyFailed is an X.509 verification failure. The least two
 | 
						|
	// significant digits of 12XX is determined as the actual x509
 | 
						|
	// error is examined.
 | 
						|
	VerifyFailed // Code 12XX
 | 
						|
 | 
						|
	// BadRequest indicates that the certificate request is invalid.
 | 
						|
	BadRequest // Code 13XX
 | 
						|
 | 
						|
	// MissingSerial indicates that the profile specified
 | 
						|
	// 'ClientProvidesSerialNumbers', but the SignRequest did not include a serial
 | 
						|
	// number.
 | 
						|
	MissingSerial // Code 14XX
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	certificateInvalid = 10 * (iota + 1) //121X
 | 
						|
	unknownAuthority                     //122x
 | 
						|
)
 | 
						|
 | 
						|
// The following represent private-key non-parsing errors, and must be
 | 
						|
// specified with PrivateKeyError.
 | 
						|
const (
 | 
						|
	// Encrypted indicates that the private key is a PKCS #8 encrypted
 | 
						|
	// private key. At this time, CFSSL does not support decrypting
 | 
						|
	// these keys.
 | 
						|
	Encrypted Reason = 100 * (iota + 1) //21XX
 | 
						|
 | 
						|
	// NotRSAOrECC indicates that they key is not an RSA or ECC
 | 
						|
	// private key; these are the only two private key types supported
 | 
						|
	// at this time by CFSSL.
 | 
						|
	NotRSAOrECC //22XX
 | 
						|
 | 
						|
	// KeyMismatch indicates that the private key does not match
 | 
						|
	// the public key or certificate being presented with the key.
 | 
						|
	KeyMismatch //23XX
 | 
						|
 | 
						|
	// GenerationFailed indicates that a private key could not
 | 
						|
	// be generated.
 | 
						|
	GenerationFailed //24XX
 | 
						|
 | 
						|
	// Unavailable indicates that a private key mechanism (such as
 | 
						|
	// PKCS #11) was requested but support for that mechanism is
 | 
						|
	// not available.
 | 
						|
	Unavailable
 | 
						|
)
 | 
						|
 | 
						|
// The following are policy-related non-parsing errors, and must be
 | 
						|
// specified along with PolicyError.
 | 
						|
const (
 | 
						|
	// NoKeyUsages indicates that the profile does not permit any
 | 
						|
	// key usages for the certificate.
 | 
						|
	NoKeyUsages Reason = 100 * (iota + 1) // 51XX
 | 
						|
 | 
						|
	// InvalidPolicy indicates that policy being requested is not
 | 
						|
	// a valid policy or does not exist.
 | 
						|
	InvalidPolicy // 52XX
 | 
						|
 | 
						|
	// InvalidRequest indicates a certificate request violated the
 | 
						|
	// constraints of the policy being applied to the request.
 | 
						|
	InvalidRequest // 53XX
 | 
						|
 | 
						|
	// UnknownProfile indicates that the profile does not exist.
 | 
						|
	UnknownProfile // 54XX
 | 
						|
 | 
						|
	UnmatchedWhitelist // 55xx
 | 
						|
)
 | 
						|
 | 
						|
// The following are API client related errors, and should be
 | 
						|
// specified with APIClientError.
 | 
						|
const (
 | 
						|
	// AuthenticationFailure occurs when the client is unable
 | 
						|
	// to obtain an authentication token for the request.
 | 
						|
	AuthenticationFailure Reason = 100 * (iota + 1)
 | 
						|
 | 
						|
	// JSONError wraps an encoding/json error.
 | 
						|
	JSONError
 | 
						|
 | 
						|
	// IOError wraps an io/ioutil error.
 | 
						|
	IOError
 | 
						|
 | 
						|
	// ClientHTTPError wraps a net/http error.
 | 
						|
	ClientHTTPError
 | 
						|
 | 
						|
	// ServerRequestFailed covers any other failures from the API
 | 
						|
	// client.
 | 
						|
	ServerRequestFailed
 | 
						|
)
 | 
						|
 | 
						|
// The following are OCSP related errors, and should be
 | 
						|
// specified with OCSPError
 | 
						|
const (
 | 
						|
	// IssuerMismatch ocurs when the certificate in the OCSP signing
 | 
						|
	// request was not issued by the CA that this responder responds for.
 | 
						|
	IssuerMismatch Reason = 100 * (iota + 1) // 81XX
 | 
						|
 | 
						|
	// InvalidStatus occurs when the OCSP signing requests includes an
 | 
						|
	// invalid value for the certificate status.
 | 
						|
	InvalidStatus
 | 
						|
)
 | 
						|
 | 
						|
// Certificate transparency related errors specified with CTError
 | 
						|
const (
 | 
						|
	// PrecertSubmissionFailed occurs when submitting a precertificate to
 | 
						|
	// a log server fails
 | 
						|
	PrecertSubmissionFailed = 100 * (iota + 1)
 | 
						|
	// CTClientConstructionFailed occurs when the construction of a new
 | 
						|
	// github.com/google/certificate-transparency client fails.
 | 
						|
	CTClientConstructionFailed
 | 
						|
	// PrecertMissingPoison occurs when a precert is passed to SignFromPrecert
 | 
						|
	// and is missing the CT poison extension.
 | 
						|
	PrecertMissingPoison
 | 
						|
	// PrecertInvalidPoison occurs when a precert is passed to SignFromPrecert
 | 
						|
	// and has a invalid CT poison extension value or the extension is not
 | 
						|
	// critical.
 | 
						|
	PrecertInvalidPoison
 | 
						|
)
 | 
						|
 | 
						|
// Certificate persistence related errors specified with CertStoreError
 | 
						|
const (
 | 
						|
	// InsertionFailed occurs when a SQL insert query failes to complete.
 | 
						|
	InsertionFailed = 100 * (iota + 1)
 | 
						|
	// RecordNotFound occurs when a SQL query targeting on one unique
 | 
						|
	// record failes to update the specified row in the table.
 | 
						|
	RecordNotFound
 | 
						|
)
 | 
						|
 | 
						|
// The error interface implementation, which formats to a JSON object string.
 | 
						|
func (e *Error) Error() string {
 | 
						|
	marshaled, err := json.Marshal(e)
 | 
						|
	if err != nil {
 | 
						|
		panic(err)
 | 
						|
	}
 | 
						|
	return string(marshaled)
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
// New returns an error that contains  an error code and message derived from
 | 
						|
// the given category, reason. Currently, to avoid confusion, it is not
 | 
						|
// allowed to create an error of category Success
 | 
						|
func New(category Category, reason Reason) *Error {
 | 
						|
	errorCode := int(category) + int(reason)
 | 
						|
	var msg string
 | 
						|
	switch category {
 | 
						|
	case OCSPError:
 | 
						|
		switch reason {
 | 
						|
		case ReadFailed:
 | 
						|
			msg = "No certificate provided"
 | 
						|
		case IssuerMismatch:
 | 
						|
			msg = "Certificate not issued by this issuer"
 | 
						|
		case InvalidStatus:
 | 
						|
			msg = "Invalid revocation status"
 | 
						|
		}
 | 
						|
	case CertificateError:
 | 
						|
		switch reason {
 | 
						|
		case Unknown:
 | 
						|
			msg = "Unknown certificate error"
 | 
						|
		case ReadFailed:
 | 
						|
			msg = "Failed to read certificate"
 | 
						|
		case DecodeFailed:
 | 
						|
			msg = "Failed to decode certificate"
 | 
						|
		case ParseFailed:
 | 
						|
			msg = "Failed to parse certificate"
 | 
						|
		case SelfSigned:
 | 
						|
			msg = "Certificate is self signed"
 | 
						|
		case VerifyFailed:
 | 
						|
			msg = "Unable to verify certificate"
 | 
						|
		case BadRequest:
 | 
						|
			msg = "Invalid certificate request"
 | 
						|
		case MissingSerial:
 | 
						|
			msg = "Missing serial number in request"
 | 
						|
		default:
 | 
						|
			panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category CertificateError.",
 | 
						|
				reason))
 | 
						|
 | 
						|
		}
 | 
						|
	case PrivateKeyError:
 | 
						|
		switch reason {
 | 
						|
		case Unknown:
 | 
						|
			msg = "Unknown private key error"
 | 
						|
		case ReadFailed:
 | 
						|
			msg = "Failed to read private key"
 | 
						|
		case DecodeFailed:
 | 
						|
			msg = "Failed to decode private key"
 | 
						|
		case ParseFailed:
 | 
						|
			msg = "Failed to parse private key"
 | 
						|
		case Encrypted:
 | 
						|
			msg = "Private key is encrypted."
 | 
						|
		case NotRSAOrECC:
 | 
						|
			msg = "Private key algorithm is not RSA or ECC"
 | 
						|
		case KeyMismatch:
 | 
						|
			msg = "Private key does not match public key"
 | 
						|
		case GenerationFailed:
 | 
						|
			msg = "Failed to new private key"
 | 
						|
		case Unavailable:
 | 
						|
			msg = "Private key is unavailable"
 | 
						|
		default:
 | 
						|
			panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category PrivateKeyError.",
 | 
						|
				reason))
 | 
						|
		}
 | 
						|
	case IntermediatesError:
 | 
						|
		switch reason {
 | 
						|
		case Unknown:
 | 
						|
			msg = "Unknown intermediate certificate error"
 | 
						|
		case ReadFailed:
 | 
						|
			msg = "Failed to read intermediate certificate"
 | 
						|
		case DecodeFailed:
 | 
						|
			msg = "Failed to decode intermediate certificate"
 | 
						|
		case ParseFailed:
 | 
						|
			msg = "Failed to parse intermediate certificate"
 | 
						|
		default:
 | 
						|
			panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category IntermediatesError.",
 | 
						|
				reason))
 | 
						|
		}
 | 
						|
	case RootError:
 | 
						|
		switch reason {
 | 
						|
		case Unknown:
 | 
						|
			msg = "Unknown root certificate error"
 | 
						|
		case ReadFailed:
 | 
						|
			msg = "Failed to read root certificate"
 | 
						|
		case DecodeFailed:
 | 
						|
			msg = "Failed to decode root certificate"
 | 
						|
		case ParseFailed:
 | 
						|
			msg = "Failed to parse root certificate"
 | 
						|
		default:
 | 
						|
			panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category RootError.",
 | 
						|
				reason))
 | 
						|
		}
 | 
						|
	case PolicyError:
 | 
						|
		switch reason {
 | 
						|
		case Unknown:
 | 
						|
			msg = "Unknown policy error"
 | 
						|
		case NoKeyUsages:
 | 
						|
			msg = "Invalid policy: no key usage available"
 | 
						|
		case InvalidPolicy:
 | 
						|
			msg = "Invalid or unknown policy"
 | 
						|
		case InvalidRequest:
 | 
						|
			msg = "Policy violation request"
 | 
						|
		case UnknownProfile:
 | 
						|
			msg = "Unknown policy profile"
 | 
						|
		case UnmatchedWhitelist:
 | 
						|
			msg = "Request does not match policy whitelist"
 | 
						|
		default:
 | 
						|
			panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category PolicyError.",
 | 
						|
				reason))
 | 
						|
		}
 | 
						|
	case DialError:
 | 
						|
		switch reason {
 | 
						|
		case Unknown:
 | 
						|
			msg = "Failed to dial remote server"
 | 
						|
		default:
 | 
						|
			panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category DialError.",
 | 
						|
				reason))
 | 
						|
		}
 | 
						|
	case APIClientError:
 | 
						|
		switch reason {
 | 
						|
		case AuthenticationFailure:
 | 
						|
			msg = "API client authentication failure"
 | 
						|
		case JSONError:
 | 
						|
			msg = "API client JSON config error"
 | 
						|
		case ClientHTTPError:
 | 
						|
			msg = "API client HTTP error"
 | 
						|
		case IOError:
 | 
						|
			msg = "API client IO error"
 | 
						|
		case ServerRequestFailed:
 | 
						|
			msg = "API client error: Server request failed"
 | 
						|
		default:
 | 
						|
			panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category APIClientError.",
 | 
						|
				reason))
 | 
						|
		}
 | 
						|
	case CSRError:
 | 
						|
		switch reason {
 | 
						|
		case Unknown:
 | 
						|
			msg = "CSR parsing failed due to unknown error"
 | 
						|
		case ReadFailed:
 | 
						|
			msg = "CSR file read failed"
 | 
						|
		case ParseFailed:
 | 
						|
			msg = "CSR Parsing failed"
 | 
						|
		case DecodeFailed:
 | 
						|
			msg = "CSR Decode failed"
 | 
						|
		case BadRequest:
 | 
						|
			msg = "CSR Bad request"
 | 
						|
		default:
 | 
						|
			panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category APIClientError.", reason))
 | 
						|
		}
 | 
						|
	case CTError:
 | 
						|
		switch reason {
 | 
						|
		case Unknown:
 | 
						|
			msg = "Certificate transparency parsing failed due to unknown error"
 | 
						|
		case PrecertSubmissionFailed:
 | 
						|
			msg = "Certificate transparency precertificate submission failed"
 | 
						|
		case PrecertMissingPoison:
 | 
						|
			msg = "Precertificate is missing CT poison extension"
 | 
						|
		case PrecertInvalidPoison:
 | 
						|
			msg = "Precertificate contains an invalid CT poison extension"
 | 
						|
		default:
 | 
						|
			panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category CTError.", reason))
 | 
						|
		}
 | 
						|
	case CertStoreError:
 | 
						|
		switch reason {
 | 
						|
		case Unknown:
 | 
						|
			msg = "Certificate store action failed due to unknown error"
 | 
						|
		default:
 | 
						|
			panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category CertStoreError.", reason))
 | 
						|
		}
 | 
						|
 | 
						|
	default:
 | 
						|
		panic(fmt.Sprintf("Unsupported CFSSL error type: %d.",
 | 
						|
			category))
 | 
						|
	}
 | 
						|
	return &Error{ErrorCode: errorCode, Message: msg}
 | 
						|
}
 | 
						|
 | 
						|
// Wrap returns an error that contains the given error and an error code derived from
 | 
						|
// the given category, reason and the error. Currently, to avoid confusion, it is not
 | 
						|
// allowed to create an error of category Success
 | 
						|
func Wrap(category Category, reason Reason, err error) *Error {
 | 
						|
	errorCode := int(category) + int(reason)
 | 
						|
	if err == nil {
 | 
						|
		panic("Wrap needs a supplied error to initialize.")
 | 
						|
	}
 | 
						|
 | 
						|
	// do not double wrap a error
 | 
						|
	switch err.(type) {
 | 
						|
	case *Error:
 | 
						|
		panic("Unable to wrap a wrapped error.")
 | 
						|
	}
 | 
						|
 | 
						|
	switch category {
 | 
						|
	case CertificateError:
 | 
						|
		// given VerifyFailed , report the status with more detailed status code
 | 
						|
		// for some certificate errors we care.
 | 
						|
		if reason == VerifyFailed {
 | 
						|
			switch errorType := err.(type) {
 | 
						|
			case x509.CertificateInvalidError:
 | 
						|
				errorCode += certificateInvalid + int(errorType.Reason)
 | 
						|
			case x509.UnknownAuthorityError:
 | 
						|
				errorCode += unknownAuthority
 | 
						|
			}
 | 
						|
		}
 | 
						|
	case PrivateKeyError, IntermediatesError, RootError, PolicyError, DialError,
 | 
						|
		APIClientError, CSRError, CTError, CertStoreError, OCSPError:
 | 
						|
	// no-op, just use the error
 | 
						|
	default:
 | 
						|
		panic(fmt.Sprintf("Unsupported CFSSL error type: %d.",
 | 
						|
			category))
 | 
						|
	}
 | 
						|
 | 
						|
	return &Error{ErrorCode: errorCode, Message: err.Error()}
 | 
						|
 | 
						|
}
 |