pkix_error.c (16059B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 /* 5 * pkix_error.c 6 * 7 * Error Object Functions 8 * 9 */ 10 11 #include "pkix_error.h" 12 13 #undef PKIX_ERRORENTRY 14 15 #define PKIX_ERRORENTRY(name,desc,nsserr) #desc 16 17 #if defined PKIX_ERROR_DESCRIPTION 18 19 const char * const PKIX_ErrorText[] = 20 { 21 #include "pkix_errorstrings.h" 22 }; 23 24 #else 25 26 #include "prprf.h" 27 28 #endif /* PKIX_ERROR_DESCRIPTION */ 29 30 extern const PKIX_Int32 PKIX_PLErrorIndex[]; 31 32 /* --Private-Functions-------------------------------------------- */ 33 34 /* 35 * FUNCTION: pkix_Error_Equals 36 * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) 37 */ 38 static PKIX_Error * 39 pkix_Error_Equals( 40 PKIX_PL_Object *firstObject, 41 PKIX_PL_Object *secondObject, 42 PKIX_Boolean *pResult, 43 void *plContext) 44 { 45 PKIX_Error *firstError = NULL; 46 PKIX_Error *secondError = NULL; 47 PKIX_Error *firstCause = NULL; 48 PKIX_Error *secondCause = NULL; 49 PKIX_PL_Object *firstInfo = NULL; 50 PKIX_PL_Object *secondInfo = NULL; 51 PKIX_ERRORCLASS firstClass, secondClass; 52 PKIX_UInt32 secondType; 53 PKIX_Boolean boolResult, unequalFlag; 54 55 PKIX_ENTER(ERROR, "pkix_Error_Equals"); 56 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); 57 58 unequalFlag = PKIX_FALSE; 59 60 /* First just compare pointer values to save time */ 61 if (firstObject == secondObject) { 62 *pResult = PKIX_TRUE; 63 goto cleanup; 64 } else { 65 /* Result will only be set to true if all tests pass */ 66 *pResult = PKIX_FALSE; 67 } 68 69 PKIX_CHECK(pkix_CheckType(firstObject, PKIX_ERROR_TYPE, plContext), 70 PKIX_FIRSTOBJECTNOTANERROROBJECT); 71 72 PKIX_CHECK(PKIX_PL_Object_GetType 73 (secondObject, &secondType, plContext), 74 PKIX_ERRORGETTINGSECONDOBJECTTYPE); 75 76 /* If types differ, then return false. Result is already set */ 77 if (secondType != PKIX_ERROR_TYPE) goto cleanup; 78 79 /* It is safe to cast to PKIX_Error */ 80 firstError = (PKIX_Error *) firstObject; 81 secondError = (PKIX_Error *) secondObject; 82 83 /* Compare error codes */ 84 firstClass = firstError->errClass; 85 secondClass = secondError->errClass; 86 87 /* If codes differ, return false. Result is already set */ 88 if (firstClass != secondClass) goto cleanup; 89 90 /* Compare causes */ 91 firstCause = firstError->cause; 92 secondCause = secondError->cause; 93 94 /* Ensure that either both or none of the causes are NULL */ 95 if (((firstCause != NULL) && (secondCause == NULL))|| 96 ((firstCause == NULL) && (secondCause != NULL))) 97 unequalFlag = PKIX_TRUE; 98 99 if ((firstCause != NULL) && (secondCause != NULL)) { 100 PKIX_CHECK(PKIX_PL_Object_Equals 101 ((PKIX_PL_Object*)firstCause, 102 (PKIX_PL_Object*)secondCause, 103 &boolResult, 104 plContext), 105 PKIX_ERRORINRECURSIVEEQUALSCALL); 106 107 /* Set the unequalFlag so that we return after dec refing */ 108 if (boolResult == 0) unequalFlag = PKIX_TRUE; 109 } 110 111 /* If the cause errors are not equal, return null */ 112 if (unequalFlag) goto cleanup; 113 114 /* Compare info fields */ 115 firstInfo = firstError->info; 116 secondInfo = secondError->info; 117 118 if (firstInfo != secondInfo) goto cleanup; 119 120 /* Ensure that either both or none of the infos are NULL */ 121 if (((firstInfo != NULL) && (secondInfo == NULL))|| 122 ((firstInfo == NULL) && (secondInfo != NULL))) 123 unequalFlag = PKIX_TRUE; 124 125 if ((firstInfo != NULL) && (secondInfo != NULL)) { 126 127 PKIX_CHECK(PKIX_PL_Object_Equals 128 ((PKIX_PL_Object*)firstInfo, 129 (PKIX_PL_Object*)secondInfo, 130 &boolResult, 131 plContext), 132 PKIX_ERRORINRECURSIVEEQUALSCALL); 133 134 /* Set the unequalFlag so that we return after dec refing */ 135 if (boolResult == 0) unequalFlag = PKIX_TRUE; 136 } 137 138 /* If the infos are not equal, return null */ 139 if (unequalFlag) goto cleanup; 140 141 142 /* Compare descs */ 143 if (firstError->errCode != secondError->errCode) { 144 unequalFlag = PKIX_TRUE; 145 } 146 147 if (firstError->plErr != secondError->plErr) { 148 unequalFlag = PKIX_TRUE; 149 } 150 151 /* If the unequalFlag was set, return false */ 152 if (unequalFlag) goto cleanup; 153 154 /* Errors are equal in all fields at this point */ 155 *pResult = PKIX_TRUE; 156 157 cleanup: 158 159 PKIX_RETURN(ERROR); 160 } 161 162 /* 163 * FUNCTION: pkix_Error_Destroy 164 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) 165 */ 166 static PKIX_Error * 167 pkix_Error_Destroy( 168 PKIX_PL_Object *object, 169 void *plContext) 170 { 171 PKIX_Error *error = NULL; 172 173 PKIX_ENTER(ERROR, "pkix_Error_Destroy"); 174 PKIX_NULLCHECK_ONE(object); 175 176 PKIX_CHECK(pkix_CheckType(object, PKIX_ERROR_TYPE, plContext), 177 PKIX_OBJECTNOTANERROR); 178 179 error = (PKIX_Error *)object; 180 181 PKIX_DECREF(error->cause); 182 183 PKIX_DECREF(error->info); 184 185 cleanup: 186 187 PKIX_RETURN(ERROR); 188 } 189 190 191 /* XXX This is not thread safe */ 192 static PKIX_UInt32 pkix_error_cause_depth = 1; 193 194 /* 195 * FUNCTION: pkix_Error_ToString 196 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) 197 */ 198 static PKIX_Error * 199 pkix_Error_ToString( 200 PKIX_PL_Object *object, 201 PKIX_PL_String **pString, 202 void *plContext) 203 { 204 PKIX_Error *error = NULL; 205 PKIX_Error *cause = NULL; 206 PKIX_PL_String *desc = NULL; 207 PKIX_PL_String *formatString = NULL; 208 PKIX_PL_String *causeString = NULL; 209 PKIX_PL_String *optCauseString = NULL; 210 PKIX_PL_String *errorNameString = NULL; 211 char *format = NULL; 212 PKIX_ERRORCLASS errClass; 213 214 PKIX_ENTER(ERROR, "pkix_Error_ToString"); 215 PKIX_NULLCHECK_TWO(object, pString); 216 217 PKIX_CHECK(pkix_CheckType(object, PKIX_ERROR_TYPE, plContext), 218 PKIX_OBJECTNOTANERROR); 219 220 error = (PKIX_Error *)object; 221 222 /* Get this error's errClass, description and the string of its cause */ 223 errClass = error->errClass; 224 225 /* Get the description string */ 226 PKIX_Error_GetDescription(error, &desc, plContext); 227 228 /* Get the cause */ 229 cause = error->cause; 230 231 /* Get the causes's description string */ 232 if (cause != NULL) { 233 pkix_error_cause_depth++; 234 235 /* Get the cause string */ 236 PKIX_CHECK(PKIX_PL_Object_ToString 237 ((PKIX_PL_Object*)cause, &causeString, plContext), 238 PKIX_ERRORGETTINGCAUSESTRING); 239 240 format = "\n*** Cause (%d): %s"; 241 242 PKIX_CHECK(PKIX_PL_String_Create 243 (PKIX_ESCASCII, 244 format, 245 0, 246 &formatString, 247 plContext), 248 PKIX_STRINGCREATEFAILED); 249 250 /* Create the optional Cause String */ 251 PKIX_CHECK(PKIX_PL_Sprintf 252 (&optCauseString, 253 plContext, 254 formatString, 255 pkix_error_cause_depth, 256 causeString), 257 PKIX_SPRINTFFAILED); 258 259 PKIX_DECREF(formatString); 260 261 pkix_error_cause_depth--; 262 } 263 264 /* Create the Format String */ 265 if (optCauseString != NULL) { 266 format = "*** %s Error- %s%s"; 267 } else { 268 format = "*** %s Error- %s"; 269 } 270 271 /* Ensure that error errClass is known, otherwise default to Object */ 272 if (errClass >= PKIX_NUMERRORCLASSES) { 273 errClass = 0; 274 } 275 276 PKIX_CHECK(PKIX_PL_String_Create 277 (PKIX_ESCASCII, 278 (void *)PKIX_ERRORCLASSNAMES[errClass], 279 0, 280 &errorNameString, 281 plContext), 282 PKIX_STRINGCREATEFAILED); 283 284 PKIX_CHECK(PKIX_PL_String_Create 285 (PKIX_ESCASCII, 286 format, 287 0, 288 &formatString, 289 plContext), 290 PKIX_STRINGCREATEFAILED); 291 292 /* Create the output String */ 293 PKIX_CHECK(PKIX_PL_Sprintf 294 (pString, 295 plContext, 296 formatString, 297 errorNameString, 298 desc, 299 optCauseString), 300 PKIX_SPRINTFFAILED); 301 302 cleanup: 303 304 PKIX_DECREF(desc); 305 PKIX_DECREF(causeString); 306 PKIX_DECREF(formatString); 307 PKIX_DECREF(optCauseString); 308 PKIX_DECREF(errorNameString); 309 310 PKIX_RETURN(ERROR); 311 } 312 313 /* 314 * FUNCTION: pkix_Error_Hashcode 315 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) 316 */ 317 static PKIX_Error * 318 pkix_Error_Hashcode( 319 PKIX_PL_Object *object, 320 PKIX_UInt32 *pResult, 321 void *plContext) 322 { 323 PKIX_ENTER(ERROR, "pkix_Error_Hashcode"); 324 PKIX_NULLCHECK_TWO(object, pResult); 325 326 /* XXX Unimplemented */ 327 /* XXX Need to make hashcodes equal when two errors are equal */ 328 *pResult = (PKIX_UInt32)((char *)object - (char *)NULL); 329 330 PKIX_RETURN(ERROR); 331 } 332 333 /* --Initializers------------------------------------------------- */ 334 335 /* 336 * PKIX_ERRORCLASSNAMES is an array of strings, with each string holding a 337 * descriptive name for an error errClass. This is used by the default 338 * PKIX_PL_Error_ToString function. 339 * 340 * Note: PKIX_ERRORCLASSES is defined in pkixt.h as a list of error types. 341 * (More precisely, as a list of invocations of ERRMACRO(type).) The 342 * macro is expanded in pkixt.h to define error numbers, and here to 343 * provide corresponding strings. For example, since the fifth ERRMACRO 344 * entry is MUTEX, then PKIX_MUTEX_ERROR is defined in pkixt.h as 4, and 345 * PKIX_ERRORCLASSNAMES[4] is initialized here with the value "MUTEX". 346 */ 347 #undef ERRMACRO 348 #define ERRMACRO(type) #type 349 350 const char * 351 PKIX_ERRORCLASSNAMES[PKIX_NUMERRORCLASSES] = 352 { 353 PKIX_ERRORCLASSES 354 }; 355 356 /* 357 * FUNCTION: pkix_Error_RegisterSelf 358 * DESCRIPTION: 359 * Registers PKIX_ERROR_TYPE and its related functions with systemClasses[] 360 * THREAD SAFETY: 361 * Not Thread Safe - for performance and complexity reasons 362 * 363 * Since this function is only called by PKIX_PL_Initialize, which should 364 * only be called once, it is acceptable that this function is not 365 * thread-safe. 366 */ 367 PKIX_Error * 368 pkix_Error_RegisterSelf(void *plContext) 369 { 370 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; 371 pkix_ClassTable_Entry entry; 372 373 PKIX_ENTER(ERROR, "pkix_Error_RegisterSelf"); 374 375 entry.description = "Error"; 376 entry.objCounter = 0; 377 entry.typeObjectSize = sizeof(PKIX_Error); 378 entry.destructor = pkix_Error_Destroy; 379 entry.equalsFunction = pkix_Error_Equals; 380 entry.hashcodeFunction = pkix_Error_Hashcode; 381 entry.toStringFunction = pkix_Error_ToString; 382 entry.comparator = NULL; 383 entry.duplicateFunction = pkix_duplicateImmutable; 384 385 systemClasses[PKIX_ERROR_TYPE] = entry; 386 387 PKIX_RETURN(ERROR); 388 } 389 390 /* --Public-Functions--------------------------------------------- */ 391 392 /* 393 * FUNCTION: PKIX_Error_Create (see comments in pkix_util.h) 394 */ 395 PKIX_Error * 396 PKIX_Error_Create( 397 PKIX_ERRORCLASS errClass, 398 PKIX_Error *cause, 399 PKIX_PL_Object *info, 400 PKIX_ERRORCODE errCode, 401 PKIX_Error **pError, 402 void *plContext) 403 { 404 PKIX_Error *tempCause = NULL; 405 PKIX_Error *error = NULL; 406 407 PKIX_ENTER(ERROR, "PKIX_Error_Create"); 408 409 PKIX_NULLCHECK_ONE(pError); 410 411 /* 412 * when called here, if PKIX_PL_Object_Alloc returns an error, 413 * it must be a PKIX_ALLOC_ERROR 414 */ 415 pkixErrorResult = PKIX_PL_Object_Alloc 416 (PKIX_ERROR_TYPE, 417 ((PKIX_UInt32)(sizeof (PKIX_Error))), 418 (PKIX_PL_Object **)&error, 419 plContext); 420 421 if (pkixErrorResult) return (pkixErrorResult); 422 423 error->errClass = errClass; 424 425 /* Ensure we don't have a loop. Follow causes until NULL */ 426 for (tempCause = cause; 427 tempCause != NULL; 428 tempCause = tempCause->cause) { 429 /* If we detect a loop, throw a new error */ 430 if (tempCause == error) { 431 PKIX_ERROR(PKIX_LOOPOFERRORCAUSEDETECTED); 432 } 433 } 434 435 PKIX_INCREF(cause); 436 error->cause = cause; 437 438 PKIX_INCREF(info); 439 error->info = info; 440 441 error->errCode = errCode; 442 443 error->plErr = PKIX_PLErrorIndex[error->errCode]; 444 445 *pError = error; 446 error = NULL; 447 448 cleanup: 449 /* PKIX-XXX Fix for leak during error creation */ 450 PKIX_DECREF(error); 451 452 PKIX_RETURN(ERROR); 453 } 454 455 /* 456 * FUNCTION: PKIX_Error_GetErrorClass (see comments in pkix_util.h) 457 */ 458 PKIX_Error * 459 PKIX_Error_GetErrorClass( 460 PKIX_Error *error, 461 PKIX_ERRORCLASS *pClass, 462 void *plContext) 463 { 464 PKIX_ENTER(ERROR, "PKIX_Error_GetErrorClass"); 465 PKIX_NULLCHECK_TWO(error, pClass); 466 467 *pClass = error->errClass; 468 469 PKIX_RETURN(ERROR); 470 } 471 472 /* 473 * FUNCTION: PKIX_Error_GetErrorCode (see comments in pkix_util.h) 474 */ 475 PKIX_Error * 476 PKIX_Error_GetErrorCode( 477 PKIX_Error *error, 478 PKIX_ERRORCODE *pCode, 479 void *plContext) 480 { 481 PKIX_ENTER(ERROR, "PKIX_Error_GetErrorCode"); 482 PKIX_NULLCHECK_TWO(error, pCode); 483 484 *pCode = error->errCode; 485 486 PKIX_RETURN(ERROR); 487 } 488 489 /* 490 * FUNCTION: PKIX_Error_GetCause (see comments in pkix_util.h) 491 */ 492 PKIX_Error * 493 PKIX_Error_GetCause( 494 PKIX_Error *error, 495 PKIX_Error **pCause, 496 void *plContext) 497 { 498 PKIX_ENTER(ERROR, "PKIX_Error_GetCause"); 499 PKIX_NULLCHECK_TWO(error, pCause); 500 501 if (error->cause != PKIX_ALLOC_ERROR()){ 502 PKIX_INCREF(error->cause); 503 } 504 505 *pCause = error->cause; 506 507 cleanup: 508 PKIX_RETURN(ERROR); 509 } 510 511 /* 512 * FUNCTION: PKIX_Error_GetSupplementaryInfo (see comments in pkix_util.h) 513 */ 514 PKIX_Error * 515 PKIX_Error_GetSupplementaryInfo( 516 PKIX_Error *error, 517 PKIX_PL_Object **pInfo, 518 void *plContext) 519 { 520 PKIX_ENTER(ERROR, "PKIX_Error_GetSupplementaryInfo"); 521 PKIX_NULLCHECK_TWO(error, pInfo); 522 523 PKIX_INCREF(error->info); 524 525 *pInfo = error->info; 526 527 cleanup: 528 PKIX_RETURN(ERROR); 529 } 530 531 /* 532 * FUNCTION: PKIX_Error_GetDescription (see comments in pkix_util.h) 533 */ 534 PKIX_Error * 535 PKIX_Error_GetDescription( 536 PKIX_Error *error, 537 PKIX_PL_String **pDesc, 538 void *plContext) 539 { 540 PKIX_PL_String *descString = NULL; 541 #ifndef PKIX_ERROR_DESCRIPTION 542 char errorStr[32]; 543 #endif 544 545 PKIX_ENTER(ERROR, "PKIX_Error_GetDescription"); 546 PKIX_NULLCHECK_TWO(error, pDesc); 547 548 #ifndef PKIX_ERROR_DESCRIPTION 549 PR_snprintf(errorStr, 32, "Error code: %d", error->errCode); 550 #endif 551 552 PKIX_PL_String_Create(PKIX_ESCASCII, 553 #if defined PKIX_ERROR_DESCRIPTION 554 (void *)PKIX_ErrorText[error->errCode], 555 #else 556 errorStr, 557 #endif 558 0, 559 &descString, 560 plContext); 561 562 *pDesc = descString; 563 564 PKIX_RETURN(ERROR); 565 }