PageRenderTime 47ms CodeModel.GetById 15ms app.highlight 27ms RepoModel.GetById 1ms app.codeStats 1ms

/security/nss/lib/libpkix/pkix/util/pkix_error.c

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