github.com/silveraid/fabric-ca@v1.1.0-preview.0.20180127000700-71974f53ab08/lib/servererror.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8                   http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package lib
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"net/http"
    23  	"reflect"
    24  
    25  	cfsslapi "github.com/cloudflare/cfssl/api"
    26  	"github.com/cloudflare/cfssl/log"
    27  	"github.com/pkg/errors"
    28  )
    29  
    30  // Error codes
    31  const (
    32  	// Unknown error code
    33  	ErrUnknown = 0
    34  	// HTTP method not allowed
    35  	ErrMethodNotAllowed = 1
    36  	// No authorization header was found in request
    37  	ErrNoAuthHdr = 2
    38  	// Failed reading the HTTP request body
    39  	ErrReadingReqBody = 3
    40  	// HTTP request body was empty but should not have been
    41  	ErrEmptyReqBody = 4
    42  	// HTTP request body was of the wrong format
    43  	ErrBadReqBody = 5
    44  	// The token in the authorization header was invalid
    45  	ErrBadReqToken = 6
    46  	// The caller does not have the "hf.Revoker" attibute
    47  	ErrNotRevoker = 7
    48  	// Certificate to be revoked was not found
    49  	ErrRevCertNotFound = 8
    50  	// Certificate to be revoked is not owned by expected user
    51  	ErrCertWrongOwner = 9
    52  	// Identity of certificate to be revoked was not found
    53  	ErrRevokeIDNotFound = 10
    54  	// User info was not found for issuee of revoked certificate
    55  	ErrRevokeUserInfoNotFound = 11
    56  	// Certificate revocation failed for another reason
    57  	ErrRevokeFailure = 12
    58  	// Failed to update user info when revoking identity
    59  	ErrRevokeUpdateUser = 13
    60  	// Failed to revoke any certificates by identity
    61  	ErrNoCertsRevoked = 14
    62  	// Missing fields in the revocation request
    63  	ErrMissingRevokeArgs = 15
    64  	// Failed to get user's affiliation
    65  	ErrGettingAffiliation = 16
    66  	// Revoker's affiliation not equal to or above revokee's affiliation
    67  	ErrRevokerNotAffiliated = 17
    68  	// Failed to send an HTTP response
    69  	ErrSendingResponse = 18
    70  	// The CA (Certificate Authority) name was not found
    71  	ErrCANotFound = 19
    72  	// Authorization failure
    73  	ErrAuthFailure = 20
    74  	// No username and password were in the authorization header
    75  	ErrNoUserPass = 21
    76  	// Enrollment is currently disabled for the server
    77  	ErrEnrollDisabled = 22
    78  	// Invalid user name
    79  	ErrInvalidUser = 23
    80  	// Invalid password
    81  	ErrInvalidPass = 24
    82  	// Invalid token in authorization header
    83  	ErrInvalidToken = 25
    84  	// Certificate was not issued by a trusted authority
    85  	ErrUntrustedCertificate = 26
    86  	// Certificate has expired
    87  	ErrCertExpired = 27
    88  	// Certificate has been revoked
    89  	ErrCertRevoked = 28
    90  	// Failed trying to check if certificate is revoked
    91  	ErrCertRevokeCheckFailure = 29
    92  	// Certificate was not found
    93  	ErrCertNotFound = 30
    94  	// Bad certificate signing request
    95  	ErrBadCSR = 31
    96  	// Failed to get identity's prekey
    97  	ErrNoPreKey = 32
    98  	// The caller was not authenticated
    99  	ErrCallerIsNotAuthenticated = 33
   100  	// Invalid configuration setting
   101  	ErrConfig = 34
   102  	// The caller does not have authority to generate a CRL
   103  	ErrNoGenCRLAuth = 35
   104  	// Invalid RevokedAfter value in the GenCRL request
   105  	ErrInvalidRevokedAfter = 36
   106  	// Invalid ExpiredAfter value in the GenCRL request
   107  	ErrInvalidExpiredAfter = 37
   108  	// Failed to get revoked certs from the database
   109  	ErrRevokedCertsFromDB = 38
   110  	// Failed to get CA cert
   111  	ErrGetCACert = 39
   112  	// Failed to get CA signer
   113  	ErrGetCASigner = 40
   114  	// Failed to generate CRL
   115  	ErrGenCRL = 41
   116  	// Registrar does not have the authority to register an attribute
   117  	ErrRegAttrAuth = 42
   118  	// Registrar does not own 'hf.Registrar.Attributes'
   119  	ErrMissingRegAttr = 43
   120  	// Caller does not have appropriate affiliation to perform requested action
   121  	ErrCallerNotAffiliated = 44
   122  	// Failed to verify if caller has appropriate type
   123  	ErrGettingType = 45
   124  	// CA cert does not have 'crl sign' usage
   125  	ErrNoCrlSignAuth = 46
   126  	// Incorrect level of database
   127  	ErrDBLevel = 47
   128  	// Incorrect level of configuration file
   129  	ErrConfigFileLevel = 48
   130  	// Failed to get user from database
   131  	ErrGettingUser = 49
   132  	// Error processing HTTP request
   133  	ErrHTTPRequest = 50
   134  	// Error connecting to database
   135  	ErrConnectingDB = 51
   136  	// Failed to add identity
   137  	ErrAddIdentity = 52
   138  	// Unauthorized to perform update action
   139  	ErrUpdateConfigAuth = 53
   140  	// Registrar not authorized to act on type
   141  	ErrRegistrarInvalidType = 54
   142  	// Registrar not authorized to act on affiliation
   143  	ErrRegistrarNotAffiliated = 55
   144  	// Failed to remove identity
   145  	ErrRemoveIdentity = 56
   146  	// Failed to get boolean query parameter
   147  	ErrGettingBoolQueryParm = 57
   148  	// Failed to modify identity
   149  	ErrModifyingIdentity = 58
   150  	// Caller does not have the appropriate role
   151  	ErrMissingRole = 59
   152  	// Failed to add new affiliation
   153  	ErrUpdateConfigAddAff = 60
   154  	// Failed to remove affiliation
   155  	ErrUpdateConfigRemoveAff = 61
   156  	// Error occured while removing affiliation in database
   157  	ErrRemoveAffDB = 62
   158  	// Error occured when making a Get request to database
   159  	ErrDBGet = 63
   160  	// Failed to modiy affiliation
   161  	ErrUpdateConfigModifyAff = 64
   162  	// Error occured while deleting user
   163  	ErrDBDeleteUser = 65
   164  	// Certificate that is being revoked has already been revoked
   165  	ErrCertAlreadyRevoked = 66
   166  )
   167  
   168  // Construct a new HTTP error.
   169  func createHTTPErr(scode, code int, format string, args ...interface{}) *httpErr {
   170  	msg := fmt.Sprintf(format, args...)
   171  	return &httpErr{
   172  		scode: scode,
   173  		lcode: code,
   174  		lmsg:  msg,
   175  		rcode: code,
   176  		rmsg:  msg,
   177  	}
   178  }
   179  
   180  // Construct a new HTTP error wrappered with pkg/errors error.
   181  func newHTTPErr(scode, code int, format string, args ...interface{}) error {
   182  	return errors.Wrap(createHTTPErr(scode, code, format, args...), "")
   183  }
   184  
   185  // Construct an HTTP error specifically indicating an authorization failure.
   186  // The local code and message is specific, but the remote code and message is generic
   187  // for security reasons.
   188  func newAuthErr(code int, format string, args ...interface{}) error {
   189  	he := createHTTPErr(401, code, format, args...)
   190  	he.Remote(ErrAuthFailure, "Authorization failure")
   191  	return errors.Wrap(he, "")
   192  }
   193  
   194  // httpErr is an HTTP error.
   195  // "local" refers to errors as logged in the server (local to the server).
   196  // "remote" refers to errors as returned to the client (remote to the server).
   197  // This allows us to log a more specific error in the server logs while
   198  // returning a more generic error to the client, as is done for authorization
   199  // failures.
   200  type httpErr struct {
   201  	scode int    // HTTP status code
   202  	lcode int    // local error code
   203  	lmsg  string // local error message
   204  	rcode int    // remote error code
   205  	rmsg  string // remote error message
   206  }
   207  
   208  // Error returns the string representation
   209  func (he *httpErr) Error() string {
   210  	return he.String()
   211  }
   212  
   213  // String returns a string representation of this augmented error
   214  func (he *httpErr) String() string {
   215  	if he.lcode == he.rcode && he.lmsg == he.rmsg {
   216  		return fmt.Sprintf("scode: %d, code: %d, msg: %s", he.scode, he.lcode, he.lmsg)
   217  	}
   218  	return fmt.Sprintf("scode: %d, local code: %d, local msg: %s, remote code: %d, remote msg: %s",
   219  		he.scode, he.lcode, he.lmsg, he.rcode, he.rmsg)
   220  }
   221  
   222  // Set the remote code and message to something different from that of the local code and message
   223  func (he *httpErr) Remote(code int, format string, args ...interface{}) *httpErr {
   224  	he.rcode = code
   225  	he.rmsg = fmt.Sprintf(format, args...)
   226  	return he
   227  }
   228  
   229  // Write the server's HTTP error response
   230  func (he *httpErr) writeResponse(w http.ResponseWriter) error {
   231  	response := cfsslapi.NewErrorResponse(he.rmsg, he.rcode)
   232  	jsonMessage, err := json.Marshal(response)
   233  	if err != nil {
   234  		log.Errorf("Failed to marshal error to JSON: %v", err)
   235  		return err
   236  	}
   237  	msg := string(jsonMessage)
   238  	http.Error(w, msg, he.scode)
   239  	return nil
   240  }
   241  
   242  type fatalErr struct {
   243  	code int
   244  	msg  string
   245  }
   246  
   247  func newFatalError(code int, format string, args ...interface{}) *fatalErr {
   248  	msg := fmt.Sprintf(format, args...)
   249  	return &fatalErr{
   250  		code: code,
   251  		msg:  msg,
   252  	}
   253  }
   254  
   255  func (fe *fatalErr) Error() string {
   256  	return fe.String()
   257  }
   258  
   259  func (fe *fatalErr) String() string {
   260  	return fmt.Sprintf("Code: %d - %s", fe.code, fe.msg)
   261  }
   262  
   263  func isFatalError(err error) bool {
   264  	causeErr := errors.Cause(err)
   265  	typ := reflect.TypeOf(causeErr)
   266  	// If a pointer to a struct is passe, get the type of the dereferenced object
   267  	if typ.Kind() == reflect.Ptr {
   268  		typ = typ.Elem()
   269  	}
   270  
   271  	if typ == reflect.TypeOf(fatalErr{}) {
   272  		return true
   273  	}
   274  	return false
   275  }