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 }