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 }