github.com/dddengyunjie/fabric-ca@v0.0.0-20190606043049-92df60ae2f0f/lib/caerrors/servererror.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package caerrors
     8  
     9  import (
    10  	"encoding/json"
    11  	"fmt"
    12  	"net/http"
    13  	"reflect"
    14  
    15  	cfsslapi "github.com/cloudflare/cfssl/api"
    16  	"github.com/cloudflare/cfssl/log"
    17  	"github.com/pkg/errors"
    18  )
    19  
    20  // Error codes
    21  const (
    22  	// Unknown error code
    23  	ErrUnknown = 0
    24  	// HTTP method not allowed
    25  	ErrMethodNotAllowed = 1
    26  	// No authorization header was found in request
    27  	ErrNoAuthHdr = 2
    28  	// Failed reading the HTTP request body
    29  	ErrReadingReqBody = 3
    30  	// HTTP request body was empty but should not have been
    31  	ErrEmptyReqBody = 4
    32  	// HTTP request body was of the wrong format
    33  	ErrBadReqBody = 5
    34  	// The token in the authorization header was invalid
    35  	ErrBadReqToken = 6
    36  	// The caller does not have the "hf.Revoker" attibute
    37  	ErrNotRevoker = 7
    38  	// Certificate to be revoked was not found
    39  	ErrRevCertNotFound = 8
    40  	// Certificate to be revoked is not owned by expected user
    41  	ErrCertWrongOwner = 9
    42  	// Identity of certificate to be revoked was not found
    43  	ErrRevokeIDNotFound = 10
    44  	// User info was not found for issuee of revoked certificate
    45  	ErrRevokeUserInfoNotFound = 11
    46  	// Certificate revocation failed for another reason
    47  	ErrRevokeFailure = 12
    48  	// Failed to update user info when revoking identity
    49  	ErrRevokeUpdateUser = 13
    50  	// Failed to revoke any certificates by identity
    51  	ErrNoCertsRevoked = 14
    52  	// Missing fields in the revocation request
    53  	ErrMissingRevokeArgs = 15
    54  	// Failed to get user's affiliation
    55  	ErrGettingAffiliation = 16
    56  	// Revoker's affiliation not equal to or above revokee's affiliation
    57  	ErrRevokerNotAffiliated = 17
    58  	// Failed to send an HTTP response
    59  	ErrSendingResponse = 18
    60  	// The CA (Certificate Authority) name was not found
    61  	ErrCANotFound = 19
    62  	// Authorization failure
    63  	ErrAuthenticationFailure = 20
    64  	// No username and password were in the authorization header
    65  	ErrNoUserPass = 21
    66  	// Enrollment is currently disabled for the server
    67  	ErrEnrollDisabled = 22
    68  	// Invalid user name
    69  	ErrInvalidUser = 23
    70  	// Invalid password
    71  	ErrInvalidPass = 24
    72  	// Invalid token in authorization header
    73  	ErrInvalidToken = 25
    74  	// Certificate was not issued by a trusted authority
    75  	ErrUntrustedCertificate = 26
    76  	// Certificate has expired
    77  	ErrCertExpired = 27
    78  	// Certificate has been revoked
    79  	ErrCertRevoked = 28
    80  	// Failed trying to check if certificate is revoked
    81  	ErrCertRevokeCheckFailure = 29
    82  	// Certificate was not found
    83  	ErrCertNotFound = 30
    84  	// Bad certificate signing request
    85  	ErrBadCSR = 31
    86  	// Failed to get identity's prekey
    87  	ErrNoPreKey = 32
    88  	// The caller was not authenticated
    89  	ErrCallerIsNotAuthenticated = 33
    90  	// Invalid configuration setting
    91  	ErrConfig = 34
    92  	// The caller does not have authority to generate a CRL
    93  	ErrNoGenCRLAuth = 35
    94  	// Invalid RevokedAfter value in the GenCRL request
    95  	ErrInvalidRevokedAfter = 36
    96  	// Invalid ExpiredAfter value in the GenCRL request
    97  	ErrInvalidExpiredAfter = 37
    98  	// Failed to get revoked certs from the database
    99  	ErrRevokedCertsFromDB = 38
   100  	// Failed to get CA cert
   101  	ErrGetCACert = 39
   102  	// Failed to get CA signer
   103  	ErrGetCASigner = 40
   104  	// Failed to generate CRL
   105  	ErrGenCRL = 41
   106  	// Registrar does not have the authority to register an attribute
   107  	ErrRegAttrAuth = 42
   108  	// Registrar does not own 'hf.Registrar.Attributes'
   109  	ErrMissingRegAttr = 43
   110  	// Caller does not have appropriate affiliation to perform requested action
   111  	ErrCallerNotAffiliated = 44
   112  	// Failed to verify if caller has appropriate type
   113  	ErrGettingType = 45
   114  	// CA cert does not have 'crl sign' usage
   115  	ErrNoCrlSignAuth = 46
   116  	// Incorrect level of database
   117  	ErrDBLevel = 47
   118  	// Incorrect level of configuration file
   119  	ErrConfigFileLevel = 48
   120  	// Failed to get user from database
   121  	ErrGettingUser = 49
   122  	// Error processing HTTP request
   123  	ErrHTTPRequest = 50
   124  	// Error connecting to database
   125  	ErrConnectingDB = 51
   126  	// Failed to add identity
   127  	ErrAddIdentity = 52
   128  	// Unauthorized to perform update action
   129  	ErrUpdateConfigAuth = 53
   130  	// Registrar not authorized to act on type
   131  	ErrRegistrarInvalidType = 54
   132  	// Registrar not authorized to act on affiliation
   133  	ErrRegistrarNotAffiliated = 55
   134  	// Failed to remove identity
   135  	ErrRemoveIdentity = 56
   136  	// Failed to get boolean query parameter
   137  	ErrGettingBoolQueryParm = 57
   138  	// Failed to modify identity
   139  	ErrModifyingIdentity = 58
   140  	// Caller does not have the appropriate role
   141  	ErrMissingRole = 59
   142  	// Failed to add new affiliation
   143  	ErrUpdateConfigAddAff = 60
   144  	// Failed to remove affiliation
   145  	ErrUpdateConfigRemoveAff = 61
   146  	// Error occured while removing affiliation in database
   147  	ErrRemoveAffDB = 62
   148  	// Error occured when making a Get request to database
   149  	ErrDBGet = 63
   150  	// Failed to modiy affiliation
   151  	ErrUpdateConfigModifyAff = 64
   152  	// Error occured while deleting user
   153  	ErrDBDeleteUser = 65
   154  	// Certificate that is being revoked has already been revoked
   155  	ErrCertAlreadyRevoked = 66
   156  	// Failed to get requested certificate(s)
   157  	ErrGettingCert = 67
   158  	// Error occurred parsing variable as an integer
   159  	ErrParsingIntEnvVar = 68
   160  	// CA certificate file is not found warning message
   161  	ErrCACertFileNotFound = 69
   162  	// Error occurs when invoking a request revoked enrollment ID
   163  	ErrRevokedID = 70
   164  	// Authorization failure
   165  	ErrAuthorizationFailure = 71
   166  	// Action is not allowed when using LDAP
   167  	ErrInvalidLDAPAction = 72
   168  	// Incorrect password limit reached
   169  	ErrPasswordAttempts = 73
   170  )
   171  
   172  // CreateHTTPErr constructs a new HTTP error.
   173  func CreateHTTPErr(scode, code int, format string, args ...interface{}) *HTTPErr {
   174  	msg := fmt.Sprintf(format, args...)
   175  	return &HTTPErr{
   176  		scode: scode,
   177  		lcode: code,
   178  		lmsg:  msg,
   179  		rcode: code,
   180  		rmsg:  msg,
   181  	}
   182  }
   183  
   184  // NewHTTPErr constructs a new HTTP error wrappered with pkg/errors error.
   185  func NewHTTPErr(scode, code int, format string, args ...interface{}) error {
   186  	return errors.Wrap(CreateHTTPErr(scode, code, format, args...), "")
   187  }
   188  
   189  // NewAuthenticationErr constructs an HTTP error specifically indicating an authentication failure.
   190  // The local code and message is specific, but the remote code and message is generic
   191  // for security reasons.
   192  func NewAuthenticationErr(code int, format string, args ...interface{}) error {
   193  	he := CreateHTTPErr(401, code, format, args...)
   194  	he.Remote(ErrAuthenticationFailure, "Authentication failure")
   195  	return errors.Wrap(he, "")
   196  }
   197  
   198  // NewAuthorizationErr constructs an HTTP error specifically indicating an authorization failure.
   199  // The local code and message is specific, but the remote code and message is generic
   200  // for security reasons.
   201  func NewAuthorizationErr(code int, format string, args ...interface{}) error {
   202  	he := CreateHTTPErr(403, code, format, args...)
   203  	he.Remote(ErrAuthorizationFailure, "Authorization failure")
   204  	return errors.Wrap(he, "")
   205  }
   206  
   207  // HTTPErr is an HTTP error.
   208  // "local" refers to errors as logged in the server (local to the server).
   209  // "remote" refers to errors as returned to the client (remote to the server).
   210  // This allows us to log a more specific error in the server logs while
   211  // returning a more generic error to the client, as is done for authorization
   212  // failures.
   213  type HTTPErr struct {
   214  	scode int    // HTTP status code
   215  	lcode int    // local error code
   216  	lmsg  string // local error message
   217  	rcode int    // remote error code
   218  	rmsg  string // remote error message
   219  }
   220  
   221  // Error returns the string representation
   222  func (he *HTTPErr) Error() string {
   223  	return he.String()
   224  }
   225  
   226  // String returns a string representation of this augmented error
   227  func (he *HTTPErr) String() string {
   228  	if he.lcode == he.rcode && he.lmsg == he.rmsg {
   229  		return fmt.Sprintf("scode: %d, code: %d, msg: %s", he.scode, he.lcode, he.lmsg)
   230  	}
   231  	return fmt.Sprintf("scode: %d, local code: %d, local msg: %s, remote code: %d, remote msg: %s",
   232  		he.scode, he.lcode, he.lmsg, he.rcode, he.rmsg)
   233  }
   234  
   235  // Remote sets the remote code and message to something different from that of the local code and message
   236  func (he *HTTPErr) Remote(code int, format string, args ...interface{}) *HTTPErr {
   237  	he.rcode = code
   238  	he.rmsg = fmt.Sprintf(format, args...)
   239  	return he
   240  }
   241  
   242  type errorWriter interface {
   243  	http.ResponseWriter
   244  }
   245  
   246  // Write the server's HTTP error response
   247  func (he *HTTPErr) writeResponse(w errorWriter) error {
   248  	response := cfsslapi.NewErrorResponse(he.rmsg, he.rcode)
   249  	jsonMessage, err := json.Marshal(response)
   250  	if err != nil {
   251  		log.Errorf("Failed to marshal error to JSON: %v", err)
   252  		return err
   253  	}
   254  	msg := string(jsonMessage)
   255  	http.Error(w, msg, he.scode)
   256  	return nil
   257  }
   258  
   259  // GetRemoteCode returns the remote error code
   260  func (he *HTTPErr) GetRemoteCode() int {
   261  	return he.rcode
   262  }
   263  
   264  // GetLocalCode returns the local error code
   265  func (he *HTTPErr) GetLocalCode() int {
   266  	return he.lcode
   267  }
   268  
   269  // GetStatusCode returns the HTTP status code
   270  func (he *HTTPErr) GetStatusCode() int {
   271  	return he.scode
   272  }
   273  
   274  // GetRemoteMsg returns the remote error message
   275  func (he *HTTPErr) GetRemoteMsg() string {
   276  	return he.rmsg
   277  }
   278  
   279  // GetLocalMsg returns the remote error message
   280  func (he *HTTPErr) GetLocalMsg() string {
   281  	return he.lmsg
   282  }
   283  
   284  // ServerErr contains error message with corresponding CA error code
   285  type ServerErr struct {
   286  	code int
   287  	msg  string
   288  }
   289  
   290  // FatalErr is a server error that is will prevent the server/CA from continuing to operate
   291  type FatalErr struct {
   292  	ServerErr
   293  }
   294  
   295  // NewServerError constructs a server error
   296  func NewServerError(code int, format string, args ...interface{}) *ServerErr {
   297  	msg := fmt.Sprintf(format, args...)
   298  	return &ServerErr{
   299  		code: code,
   300  		msg:  msg,
   301  	}
   302  }
   303  
   304  // NewFatalError constructs a fatal error
   305  func NewFatalError(code int, format string, args ...interface{}) *FatalErr {
   306  	msg := fmt.Sprintf(format, args...)
   307  	return &FatalErr{
   308  		ServerErr{
   309  			code: code,
   310  			msg:  msg,
   311  		},
   312  	}
   313  }
   314  
   315  func (fe *FatalErr) Error() string {
   316  	return fe.String()
   317  }
   318  
   319  func (fe *FatalErr) String() string {
   320  	return fmt.Sprintf("Code: %d - %s", fe.code, fe.msg)
   321  }
   322  
   323  // IsFatalError return true if the error is of type 'FatalErr'
   324  func IsFatalError(err error) bool {
   325  	causeErr := errors.Cause(err)
   326  	typ := reflect.TypeOf(causeErr)
   327  	// If a pointer to a struct is passe, get the type of the dereferenced object
   328  	if typ.Kind() == reflect.Ptr {
   329  		typ = typ.Elem()
   330  	}
   331  
   332  	if typ == reflect.TypeOf(FatalErr{}) {
   333  		return true
   334  	}
   335  	return false
   336  }