1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/libpkix/pkix/util/pkix_error.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,565 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +/* 1.8 + * pkix_error.c 1.9 + * 1.10 + * Error Object Functions 1.11 + * 1.12 + */ 1.13 + 1.14 +#include "pkix_error.h" 1.15 + 1.16 +#undef PKIX_ERRORENTRY 1.17 + 1.18 +#define PKIX_ERRORENTRY(name,desc,nsserr) #desc 1.19 + 1.20 +#if defined PKIX_ERROR_DESCRIPTION 1.21 + 1.22 +const char * const PKIX_ErrorText[] = 1.23 +{ 1.24 +#include "pkix_errorstrings.h" 1.25 +}; 1.26 + 1.27 +#else 1.28 + 1.29 +#include "prprf.h" 1.30 + 1.31 +#endif /* PKIX_ERROR_DESCRIPTION */ 1.32 + 1.33 +extern const PKIX_Int32 PKIX_PLErrorIndex[]; 1.34 + 1.35 +/* --Private-Functions-------------------------------------------- */ 1.36 + 1.37 +/* 1.38 + * FUNCTION: pkix_Error_Equals 1.39 + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) 1.40 + */ 1.41 +static PKIX_Error * 1.42 +pkix_Error_Equals( 1.43 + PKIX_PL_Object *firstObject, 1.44 + PKIX_PL_Object *secondObject, 1.45 + PKIX_Boolean *pResult, 1.46 + void *plContext) 1.47 +{ 1.48 + PKIX_Error *firstError = NULL; 1.49 + PKIX_Error *secondError = NULL; 1.50 + PKIX_Error *firstCause = NULL; 1.51 + PKIX_Error *secondCause = NULL; 1.52 + PKIX_PL_Object *firstInfo = NULL; 1.53 + PKIX_PL_Object *secondInfo = NULL; 1.54 + PKIX_ERRORCLASS firstClass, secondClass; 1.55 + PKIX_UInt32 secondType; 1.56 + PKIX_Boolean boolResult, unequalFlag; 1.57 + 1.58 + PKIX_ENTER(ERROR, "pkix_Error_Equals"); 1.59 + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); 1.60 + 1.61 + unequalFlag = PKIX_FALSE; 1.62 + 1.63 + /* First just compare pointer values to save time */ 1.64 + if (firstObject == secondObject) { 1.65 + *pResult = PKIX_TRUE; 1.66 + goto cleanup; 1.67 + } else { 1.68 + /* Result will only be set to true if all tests pass */ 1.69 + *pResult = PKIX_FALSE; 1.70 + } 1.71 + 1.72 + PKIX_CHECK(pkix_CheckType(firstObject, PKIX_ERROR_TYPE, plContext), 1.73 + PKIX_FIRSTOBJECTNOTANERROROBJECT); 1.74 + 1.75 + PKIX_CHECK(PKIX_PL_Object_GetType 1.76 + (secondObject, &secondType, plContext), 1.77 + PKIX_ERRORGETTINGSECONDOBJECTTYPE); 1.78 + 1.79 + /* If types differ, then return false. Result is already set */ 1.80 + if (secondType != PKIX_ERROR_TYPE) goto cleanup; 1.81 + 1.82 + /* It is safe to cast to PKIX_Error */ 1.83 + firstError = (PKIX_Error *) firstObject; 1.84 + secondError = (PKIX_Error *) secondObject; 1.85 + 1.86 + /* Compare error codes */ 1.87 + firstClass = firstError->errClass; 1.88 + secondClass = secondError->errClass; 1.89 + 1.90 + /* If codes differ, return false. Result is already set */ 1.91 + if (firstClass != secondClass) goto cleanup; 1.92 + 1.93 + /* Compare causes */ 1.94 + firstCause = firstError->cause; 1.95 + secondCause = secondError->cause; 1.96 + 1.97 + /* Ensure that either both or none of the causes are NULL */ 1.98 + if (((firstCause != NULL) && (secondCause == NULL))|| 1.99 + ((firstCause == NULL) && (secondCause != NULL))) 1.100 + unequalFlag = PKIX_TRUE; 1.101 + 1.102 + if ((firstCause != NULL) && (secondCause != NULL)) { 1.103 + PKIX_CHECK(PKIX_PL_Object_Equals 1.104 + ((PKIX_PL_Object*)firstCause, 1.105 + (PKIX_PL_Object*)secondCause, 1.106 + &boolResult, 1.107 + plContext), 1.108 + PKIX_ERRORINRECURSIVEEQUALSCALL); 1.109 + 1.110 + /* Set the unequalFlag so that we return after dec refing */ 1.111 + if (boolResult == 0) unequalFlag = PKIX_TRUE; 1.112 + } 1.113 + 1.114 + /* If the cause errors are not equal, return null */ 1.115 + if (unequalFlag) goto cleanup; 1.116 + 1.117 + /* Compare info fields */ 1.118 + firstInfo = firstError->info; 1.119 + secondInfo = secondError->info; 1.120 + 1.121 + if (firstInfo != secondInfo) goto cleanup; 1.122 + 1.123 + /* Ensure that either both or none of the infos are NULL */ 1.124 + if (((firstInfo != NULL) && (secondInfo == NULL))|| 1.125 + ((firstInfo == NULL) && (secondInfo != NULL))) 1.126 + unequalFlag = PKIX_TRUE; 1.127 + 1.128 + if ((firstInfo != NULL) && (secondInfo != NULL)) { 1.129 + 1.130 + PKIX_CHECK(PKIX_PL_Object_Equals 1.131 + ((PKIX_PL_Object*)firstInfo, 1.132 + (PKIX_PL_Object*)secondInfo, 1.133 + &boolResult, 1.134 + plContext), 1.135 + PKIX_ERRORINRECURSIVEEQUALSCALL); 1.136 + 1.137 + /* Set the unequalFlag so that we return after dec refing */ 1.138 + if (boolResult == 0) unequalFlag = PKIX_TRUE; 1.139 + } 1.140 + 1.141 + /* If the infos are not equal, return null */ 1.142 + if (unequalFlag) goto cleanup; 1.143 + 1.144 + 1.145 + /* Compare descs */ 1.146 + if (firstError->errCode != secondError->errCode) { 1.147 + unequalFlag = PKIX_TRUE; 1.148 + } 1.149 + 1.150 + if (firstError->plErr != secondError->plErr) { 1.151 + unequalFlag = PKIX_TRUE; 1.152 + } 1.153 + 1.154 + /* If the unequalFlag was set, return false */ 1.155 + if (unequalFlag) goto cleanup; 1.156 + 1.157 + /* Errors are equal in all fields at this point */ 1.158 + *pResult = PKIX_TRUE; 1.159 + 1.160 +cleanup: 1.161 + 1.162 + PKIX_RETURN(ERROR); 1.163 +} 1.164 + 1.165 +/* 1.166 + * FUNCTION: pkix_Error_Destroy 1.167 + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) 1.168 + */ 1.169 +static PKIX_Error * 1.170 +pkix_Error_Destroy( 1.171 + PKIX_PL_Object *object, 1.172 + void *plContext) 1.173 +{ 1.174 + PKIX_Error *error = NULL; 1.175 + 1.176 + PKIX_ENTER(ERROR, "pkix_Error_Destroy"); 1.177 + PKIX_NULLCHECK_ONE(object); 1.178 + 1.179 + PKIX_CHECK(pkix_CheckType(object, PKIX_ERROR_TYPE, plContext), 1.180 + PKIX_OBJECTNOTANERROR); 1.181 + 1.182 + error = (PKIX_Error *)object; 1.183 + 1.184 + PKIX_DECREF(error->cause); 1.185 + 1.186 + PKIX_DECREF(error->info); 1.187 + 1.188 +cleanup: 1.189 + 1.190 + PKIX_RETURN(ERROR); 1.191 +} 1.192 + 1.193 + 1.194 +/* XXX This is not thread safe */ 1.195 +static PKIX_UInt32 pkix_error_cause_depth = 1; 1.196 + 1.197 +/* 1.198 + * FUNCTION: pkix_Error_ToString 1.199 + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) 1.200 + */ 1.201 +static PKIX_Error * 1.202 +pkix_Error_ToString( 1.203 + PKIX_PL_Object *object, 1.204 + PKIX_PL_String **pString, 1.205 + void *plContext) 1.206 +{ 1.207 + PKIX_Error *error = NULL; 1.208 + PKIX_Error *cause = NULL; 1.209 + PKIX_PL_String *desc = NULL; 1.210 + PKIX_PL_String *formatString = NULL; 1.211 + PKIX_PL_String *causeString = NULL; 1.212 + PKIX_PL_String *optCauseString = NULL; 1.213 + PKIX_PL_String *errorNameString = NULL; 1.214 + char *format = NULL; 1.215 + PKIX_ERRORCLASS errClass; 1.216 + 1.217 + PKIX_ENTER(ERROR, "pkix_Error_ToString"); 1.218 + PKIX_NULLCHECK_TWO(object, pString); 1.219 + 1.220 + PKIX_CHECK(pkix_CheckType(object, PKIX_ERROR_TYPE, plContext), 1.221 + PKIX_OBJECTNOTANERROR); 1.222 + 1.223 + error = (PKIX_Error *)object; 1.224 + 1.225 + /* Get this error's errClass, description and the string of its cause */ 1.226 + errClass = error->errClass; 1.227 + 1.228 + /* Get the description string */ 1.229 + PKIX_Error_GetDescription(error, &desc, plContext); 1.230 + 1.231 + /* Get the cause */ 1.232 + cause = error->cause; 1.233 + 1.234 + /* Get the causes's description string */ 1.235 + if (cause != NULL) { 1.236 + pkix_error_cause_depth++; 1.237 + 1.238 + /* Get the cause string */ 1.239 + PKIX_CHECK(PKIX_PL_Object_ToString 1.240 + ((PKIX_PL_Object*)cause, &causeString, plContext), 1.241 + PKIX_ERRORGETTINGCAUSESTRING); 1.242 + 1.243 + format = "\n*** Cause (%d): %s"; 1.244 + 1.245 + PKIX_CHECK(PKIX_PL_String_Create 1.246 + (PKIX_ESCASCII, 1.247 + format, 1.248 + 0, 1.249 + &formatString, 1.250 + plContext), 1.251 + PKIX_STRINGCREATEFAILED); 1.252 + 1.253 + /* Create the optional Cause String */ 1.254 + PKIX_CHECK(PKIX_PL_Sprintf 1.255 + (&optCauseString, 1.256 + plContext, 1.257 + formatString, 1.258 + pkix_error_cause_depth, 1.259 + causeString), 1.260 + PKIX_SPRINTFFAILED); 1.261 + 1.262 + PKIX_DECREF(formatString); 1.263 + 1.264 + pkix_error_cause_depth--; 1.265 + } 1.266 + 1.267 + /* Create the Format String */ 1.268 + if (optCauseString != NULL) { 1.269 + format = "*** %s Error- %s%s"; 1.270 + } else { 1.271 + format = "*** %s Error- %s"; 1.272 + } 1.273 + 1.274 + /* Ensure that error errClass is known, otherwise default to Object */ 1.275 + if (errClass >= PKIX_NUMERRORCLASSES) { 1.276 + errClass = 0; 1.277 + } 1.278 + 1.279 + PKIX_CHECK(PKIX_PL_String_Create 1.280 + (PKIX_ESCASCII, 1.281 + (void *)PKIX_ERRORCLASSNAMES[errClass], 1.282 + 0, 1.283 + &errorNameString, 1.284 + plContext), 1.285 + PKIX_STRINGCREATEFAILED); 1.286 + 1.287 + PKIX_CHECK(PKIX_PL_String_Create 1.288 + (PKIX_ESCASCII, 1.289 + format, 1.290 + 0, 1.291 + &formatString, 1.292 + plContext), 1.293 + PKIX_STRINGCREATEFAILED); 1.294 + 1.295 + /* Create the output String */ 1.296 + PKIX_CHECK(PKIX_PL_Sprintf 1.297 + (pString, 1.298 + plContext, 1.299 + formatString, 1.300 + errorNameString, 1.301 + desc, 1.302 + optCauseString), 1.303 + PKIX_SPRINTFFAILED); 1.304 + 1.305 +cleanup: 1.306 + 1.307 + PKIX_DECREF(desc); 1.308 + PKIX_DECREF(causeString); 1.309 + PKIX_DECREF(formatString); 1.310 + PKIX_DECREF(optCauseString); 1.311 + PKIX_DECREF(errorNameString); 1.312 + 1.313 + PKIX_RETURN(ERROR); 1.314 +} 1.315 + 1.316 +/* 1.317 + * FUNCTION: pkix_Error_Hashcode 1.318 + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) 1.319 + */ 1.320 +static PKIX_Error * 1.321 +pkix_Error_Hashcode( 1.322 + PKIX_PL_Object *object, 1.323 + PKIX_UInt32 *pResult, 1.324 + void *plContext) 1.325 +{ 1.326 + PKIX_ENTER(ERROR, "pkix_Error_Hashcode"); 1.327 + PKIX_NULLCHECK_TWO(object, pResult); 1.328 + 1.329 + /* XXX Unimplemented */ 1.330 + /* XXX Need to make hashcodes equal when two errors are equal */ 1.331 + *pResult = (PKIX_UInt32)object; 1.332 + 1.333 + PKIX_RETURN(ERROR); 1.334 +} 1.335 + 1.336 +/* --Initializers------------------------------------------------- */ 1.337 + 1.338 +/* 1.339 + * PKIX_ERRORCLASSNAMES is an array of strings, with each string holding a 1.340 + * descriptive name for an error errClass. This is used by the default 1.341 + * PKIX_PL_Error_ToString function. 1.342 + * 1.343 + * Note: PKIX_ERRORCLASSES is defined in pkixt.h as a list of error types. 1.344 + * (More precisely, as a list of invocations of ERRMACRO(type).) The 1.345 + * macro is expanded in pkixt.h to define error numbers, and here to 1.346 + * provide corresponding strings. For example, since the fifth ERRMACRO 1.347 + * entry is MUTEX, then PKIX_MUTEX_ERROR is defined in pkixt.h as 4, and 1.348 + * PKIX_ERRORCLASSNAMES[4] is initialized here with the value "MUTEX". 1.349 + */ 1.350 +#undef ERRMACRO 1.351 +#define ERRMACRO(type) #type 1.352 + 1.353 +const char * 1.354 +PKIX_ERRORCLASSNAMES[PKIX_NUMERRORCLASSES] = 1.355 +{ 1.356 + PKIX_ERRORCLASSES 1.357 +}; 1.358 + 1.359 +/* 1.360 + * FUNCTION: pkix_Error_RegisterSelf 1.361 + * DESCRIPTION: 1.362 + * Registers PKIX_ERROR_TYPE and its related functions with systemClasses[] 1.363 + * THREAD SAFETY: 1.364 + * Not Thread Safe - for performance and complexity reasons 1.365 + * 1.366 + * Since this function is only called by PKIX_PL_Initialize, which should 1.367 + * only be called once, it is acceptable that this function is not 1.368 + * thread-safe. 1.369 + */ 1.370 +PKIX_Error * 1.371 +pkix_Error_RegisterSelf(void *plContext) 1.372 +{ 1.373 + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; 1.374 + pkix_ClassTable_Entry entry; 1.375 + 1.376 + PKIX_ENTER(ERROR, "pkix_Error_RegisterSelf"); 1.377 + 1.378 + entry.description = "Error"; 1.379 + entry.objCounter = 0; 1.380 + entry.typeObjectSize = sizeof(PKIX_Error); 1.381 + entry.destructor = pkix_Error_Destroy; 1.382 + entry.equalsFunction = pkix_Error_Equals; 1.383 + entry.hashcodeFunction = pkix_Error_Hashcode; 1.384 + entry.toStringFunction = pkix_Error_ToString; 1.385 + entry.comparator = NULL; 1.386 + entry.duplicateFunction = pkix_duplicateImmutable; 1.387 + 1.388 + systemClasses[PKIX_ERROR_TYPE] = entry; 1.389 + 1.390 + PKIX_RETURN(ERROR); 1.391 +} 1.392 + 1.393 +/* --Public-Functions--------------------------------------------- */ 1.394 + 1.395 +/* 1.396 + * FUNCTION: PKIX_Error_Create (see comments in pkix_util.h) 1.397 + */ 1.398 +PKIX_Error * 1.399 +PKIX_Error_Create( 1.400 + PKIX_ERRORCLASS errClass, 1.401 + PKIX_Error *cause, 1.402 + PKIX_PL_Object *info, 1.403 + PKIX_ERRORCODE errCode, 1.404 + PKIX_Error **pError, 1.405 + void *plContext) 1.406 +{ 1.407 + PKIX_Error *tempCause = NULL; 1.408 + PKIX_Error *error = NULL; 1.409 + 1.410 + PKIX_ENTER(ERROR, "PKIX_Error_Create"); 1.411 + 1.412 + PKIX_NULLCHECK_ONE(pError); 1.413 + 1.414 + /* 1.415 + * when called here, if PKIX_PL_Object_Alloc returns an error, 1.416 + * it must be a PKIX_ALLOC_ERROR 1.417 + */ 1.418 + pkixErrorResult = PKIX_PL_Object_Alloc 1.419 + (PKIX_ERROR_TYPE, 1.420 + ((PKIX_UInt32)(sizeof (PKIX_Error))), 1.421 + (PKIX_PL_Object **)&error, 1.422 + plContext); 1.423 + 1.424 + if (pkixErrorResult) return (pkixErrorResult); 1.425 + 1.426 + error->errClass = errClass; 1.427 + 1.428 + /* Ensure we don't have a loop. Follow causes until NULL */ 1.429 + for (tempCause = cause; 1.430 + tempCause != NULL; 1.431 + tempCause = tempCause->cause) { 1.432 + /* If we detect a loop, throw a new error */ 1.433 + if (tempCause == error) { 1.434 + PKIX_ERROR(PKIX_LOOPOFERRORCAUSEDETECTED); 1.435 + } 1.436 + } 1.437 + 1.438 + PKIX_INCREF(cause); 1.439 + error->cause = cause; 1.440 + 1.441 + PKIX_INCREF(info); 1.442 + error->info = info; 1.443 + 1.444 + error->errCode = errCode; 1.445 + 1.446 + error->plErr = PKIX_PLErrorIndex[error->errCode]; 1.447 + 1.448 + *pError = error; 1.449 + error = NULL; 1.450 + 1.451 +cleanup: 1.452 + /* PKIX-XXX Fix for leak during error creation */ 1.453 + PKIX_DECREF(error); 1.454 + 1.455 + PKIX_RETURN(ERROR); 1.456 +} 1.457 + 1.458 +/* 1.459 + * FUNCTION: PKIX_Error_GetErrorClass (see comments in pkix_util.h) 1.460 + */ 1.461 +PKIX_Error * 1.462 +PKIX_Error_GetErrorClass( 1.463 + PKIX_Error *error, 1.464 + PKIX_ERRORCLASS *pClass, 1.465 + void *plContext) 1.466 +{ 1.467 + PKIX_ENTER(ERROR, "PKIX_Error_GetErrorClass"); 1.468 + PKIX_NULLCHECK_TWO(error, pClass); 1.469 + 1.470 + *pClass = error->errClass; 1.471 + 1.472 + PKIX_RETURN(ERROR); 1.473 +} 1.474 + 1.475 +/* 1.476 + * FUNCTION: PKIX_Error_GetErrorCode (see comments in pkix_util.h) 1.477 + */ 1.478 +PKIX_Error * 1.479 +PKIX_Error_GetErrorCode( 1.480 + PKIX_Error *error, 1.481 + PKIX_ERRORCODE *pCode, 1.482 + void *plContext) 1.483 +{ 1.484 + PKIX_ENTER(ERROR, "PKIX_Error_GetErrorCode"); 1.485 + PKIX_NULLCHECK_TWO(error, pCode); 1.486 + 1.487 + *pCode = error->errCode; 1.488 + 1.489 + PKIX_RETURN(ERROR); 1.490 +} 1.491 + 1.492 +/* 1.493 + * FUNCTION: PKIX_Error_GetCause (see comments in pkix_util.h) 1.494 + */ 1.495 +PKIX_Error * 1.496 +PKIX_Error_GetCause( 1.497 + PKIX_Error *error, 1.498 + PKIX_Error **pCause, 1.499 + void *plContext) 1.500 +{ 1.501 + PKIX_ENTER(ERROR, "PKIX_Error_GetCause"); 1.502 + PKIX_NULLCHECK_TWO(error, pCause); 1.503 + 1.504 + if (error->cause != PKIX_ALLOC_ERROR()){ 1.505 + PKIX_INCREF(error->cause); 1.506 + } 1.507 + 1.508 + *pCause = error->cause; 1.509 + 1.510 +cleanup: 1.511 + PKIX_RETURN(ERROR); 1.512 +} 1.513 + 1.514 +/* 1.515 + * FUNCTION: PKIX_Error_GetSupplementaryInfo (see comments in pkix_util.h) 1.516 + */ 1.517 +PKIX_Error * 1.518 +PKIX_Error_GetSupplementaryInfo( 1.519 + PKIX_Error *error, 1.520 + PKIX_PL_Object **pInfo, 1.521 + void *plContext) 1.522 +{ 1.523 + PKIX_ENTER(ERROR, "PKIX_Error_GetSupplementaryInfo"); 1.524 + PKIX_NULLCHECK_TWO(error, pInfo); 1.525 + 1.526 + PKIX_INCREF(error->info); 1.527 + 1.528 + *pInfo = error->info; 1.529 + 1.530 +cleanup: 1.531 + PKIX_RETURN(ERROR); 1.532 +} 1.533 + 1.534 +/* 1.535 + * FUNCTION: PKIX_Error_GetDescription (see comments in pkix_util.h) 1.536 + */ 1.537 +PKIX_Error * 1.538 +PKIX_Error_GetDescription( 1.539 + PKIX_Error *error, 1.540 + PKIX_PL_String **pDesc, 1.541 + void *plContext) 1.542 +{ 1.543 + PKIX_PL_String *descString = NULL; 1.544 +#ifndef PKIX_ERROR_DESCRIPTION 1.545 + char errorStr[32]; 1.546 +#endif 1.547 + 1.548 + PKIX_ENTER(ERROR, "PKIX_Error_GetDescription"); 1.549 + PKIX_NULLCHECK_TWO(error, pDesc); 1.550 + 1.551 +#ifndef PKIX_ERROR_DESCRIPTION 1.552 + PR_snprintf(errorStr, 32, "Error code: %d", error->errCode); 1.553 +#endif 1.554 + 1.555 + PKIX_PL_String_Create(PKIX_ESCASCII, 1.556 +#if defined PKIX_ERROR_DESCRIPTION 1.557 + (void *)PKIX_ErrorText[error->errCode], 1.558 +#else 1.559 + errorStr, 1.560 +#endif 1.561 + 0, 1.562 + &descString, 1.563 + plContext); 1.564 + 1.565 + *pDesc = descString; 1.566 + 1.567 + PKIX_RETURN(ERROR); 1.568 +}