Back to index

lightning-sunbird  0.9+nobinonly
Functions | Variables
oid.c File Reference
#include "base.h"
#include "pki1.h"
#include "plhash.h"
#include "plstr.h"

Go to the source code of this file.

Functions

NSS_EXTERN NSSOID * NSSOID_CreateFromBER (NSSBER *berOid)
NSS_EXTERN NSSOID * NSSOID_CreateFromUTF8 (NSSUTF8 *stringOid)
NSS_EXTERN NSSDERNSSOID_GetDEREncoding (const NSSOID *oid, NSSDER *rvOpt, NSSArena *arenaOpt)
NSS_EXTERN NSSUTF8NSSOID_GetUTF8Encoding (const NSSOID *oid, NSSArena *arenaOpt)
static PLHashNumber PR_CALLBACK oid_hash (const void *key)
static PRIntn PR_CALLBACK oid_hash_compare (const void *k1, const void *k2)
static PRStatus PR_CALLBACK oid_once_func (void)
static PRStatus oid_init (void)
static PRStatus oid_sanity_check_ber (NSSBER *berOid)
NSS_EXTERN NSSOID * nssOID_CreateFromBER (NSSBER *berOid)
static PRStatus oid_sanity_check_utf8 (NSSUTF8 *s)
static PRUint32 oid_encode_number (PRUint32 n, PRUint8 *dp, PRUint32 nb)
static PRUint32 oid_encode_huge (NSSUTF8 *s, NSSUTF8 *e, PRUint8 *dp, PRUint32 nb)
static NSSOID * oid_encode_string (NSSUTF8 *s)
NSS_EXTERN NSSOID * nssOID_CreateFromUTF8 (NSSUTF8 *stringOid)
NSS_EXTERN NSSDERnssOID_GetDEREncoding (const NSSOID *oid, NSSDER *rvOpt, NSSArena *arenaOpt)
NSS_EXTERN NSSUTF8nssOID_GetUTF8Encoding (const NSSOID *oid, NSSArena *arenaOpt)

Variables

const NSSOID * NSS_OID_UNKNOWN = (NSSOID *)NULL
static PLHashTableoid_hash_table
static PZLockoid_hash_lock
static NSSArena * oid_arena
static PRCallOnceType oid_call_once
const NSSError NSS_ERROR_INTERNAL_ERROR

Function Documentation

NSS_EXTERN NSSOID* NSSOID_CreateFromBER ( NSSBER berOid)

Definition at line 110 of file oid.c.

{
  nss_ClearErrorStack();

#ifdef DEBUG
  /* 
   * NSSBERs can be created by the user, 
   * so no pointer-tracking can be checked.
   */

  if( (NSSBER *)NULL == berOid ) {
    nss_SetError(NSS_ERROR_INVALID_BER);
    return (NSSOID *)NULL;
  }

  if( (void *)NULL == berOid->data ) {
    nss_SetError(NSS_ERROR_INVALID_BER);
    return (NSSOID *)NULL;
  }
#endif /* DEBUG */
  
  return nssOID_CreateFromBER(berOid);
}
NSS_EXTERN NSSOID* nssOID_CreateFromBER ( NSSBER berOid)

Definition at line 644 of file oid.c.

{
  NSSOID *rv;
  PLHashEntry *e;
  
  if( PR_SUCCESS != oid_init() ) {
    return (NSSOID *)NULL;
  }

  if( PR_SUCCESS != oid_sanity_check_ber(berOid) ) {
    nss_SetError(NSS_ERROR_INVALID_BER);
    return (NSSOID *)NULL;
  }

  /*
   * Does it exist?
   */
  PZ_Lock(oid_hash_lock);
  rv = (NSSOID *)PL_HashTableLookup(oid_hash_table, berOid);
  (void)PZ_Unlock(oid_hash_lock);
  if( (NSSOID *)NULL != rv ) {
    /* Found it! */
    return rv;
  }

  /*
   * Doesn't exist-- create it.
   */
  rv = nss_ZNEW(oid_arena, NSSOID);
  if( (NSSOID *)NULL == rv ) {
    return (NSSOID *)NULL;
  }

  rv->data.data = nss_ZAlloc(oid_arena, berOid->size);
  if( (void *)NULL == rv->data.data ) {
    return (NSSOID *)NULL;
  }

  rv->data.size = berOid->size;
  nsslibc_memcpy(rv->data.data, berOid->data, berOid->size);

#ifdef DEBUG
  rv->tag = "<runtime>";
  rv->expl = "(OID registered at runtime)";
#endif /* DEBUG */

  PZ_Lock(oid_hash_lock);
  e = PL_HashTableAdd(oid_hash_table, &rv->data, rv);
  (void)PZ_Unlock(oid_hash_lock);
  if( (PLHashEntry *)NULL == e ) {
    nss_ZFreeIf(rv->data.data);
    nss_ZFreeIf(rv);
    nss_SetError(NSS_ERROR_NO_MEMORY);
    return (NSSOID *)NULL;
  }

#ifdef DEBUG
  {
    PRStatus st;
    st = oid_add_pointer(rv);
    if( PR_SUCCESS != st ) {
      PZ_Lock(oid_hash_lock);
      (void)PL_HashTableRemove(oid_hash_table, &rv->data);
      (void)PZ_Unlock(oid_hash_lock);
      (void)nss_ZFreeIf(rv->data.data);
      (void)nss_ZFreeIf(rv);
      return (NSSOID *)NULL;
    }
  }
#endif /* DEBUG */

  return rv;
}

Here is the caller graph for this function:

NSS_EXTERN NSSOID* NSSOID_CreateFromUTF8 ( NSSUTF8 stringOid)

Definition at line 155 of file oid.c.

{
  nss_ClearErrorStack();

#ifdef DEBUG
  /*
   * NSSUTF8s can be created by the user,
   * so no pointer-tracking can be checked.
   */

  if( (NSSUTF8 *)NULL == stringOid ) {
    nss_SetError(NSS_ERROR_INVALID_UTF8);
    return (NSSOID *)NULL;
  }
#endif /* DEBUG */

  return nssOID_CreateFromUTF8(stringOid);
}
NSS_EXTERN NSSOID* nssOID_CreateFromUTF8 ( NSSUTF8 stringOid)

Definition at line 1102 of file oid.c.

{
  NSSOID *rv = (NSSOID *)NULL;
  NSSOID *candidate = (NSSOID *)NULL;
  PLHashEntry *e;

  if( PR_SUCCESS != oid_init() ) {
    return (NSSOID *)NULL;
  }

  if( PR_SUCCESS != oid_sanity_check_utf8(stringOid) ) {
    nss_SetError(NSS_ERROR_INVALID_STRING);
    return (NSSOID *)NULL;
  }

  candidate = oid_encode_string(stringOid);
  if( (NSSOID *)NULL == candidate ) {
    /* Internal error only */
    return rv;
  }

  /*
   * Does it exist?
   */
  PZ_Lock(oid_hash_lock);
  rv = (NSSOID *)PL_HashTableLookup(oid_hash_table, &candidate->data);
  (void)PZ_Unlock(oid_hash_lock);
  if( (NSSOID *)NULL != rv ) {
    /* Already exists.  Delete my copy and return the original. */
    (void)nss_ZFreeIf(candidate->data.data);
    (void)nss_ZFreeIf(candidate);
    return rv;
  }

  /* 
   * Nope.  Add it.  Remember to allocate it out of the oid arena.
   */

  rv = nss_ZNEW(oid_arena, NSSOID);
  if( (NSSOID *)NULL == rv ) {
    goto loser;
  }

  rv->data.data = nss_ZAlloc(oid_arena, candidate->data.size);
  if( (void *)NULL == rv->data.data ) {
    goto loser;
  }

  rv->data.size = candidate->data.size;
  nsslibc_memcpy(rv->data.data, candidate->data.data, rv->data.size);

  (void)nss_ZFreeIf(candidate->data.data);
  (void)nss_ZFreeIf(candidate);

#ifdef DEBUG
  rv->tag = "<runtime>";
  rv->expl = "(OID registered at runtime)";
#endif /* DEBUG */

  PZ_Lock(oid_hash_lock);
  e = PL_HashTableAdd(oid_hash_table, &rv->data, rv);
  (void)PZ_Unlock(oid_hash_lock);
  if( (PLHashEntry *)NULL == e ) {
    nss_SetError(NSS_ERROR_NO_MEMORY);
    goto loser;
  }

#ifdef DEBUG
  {
    PRStatus st;
    st = oid_add_pointer(rv);
    if( PR_SUCCESS != st ) {
      PZ_Lock(oid_hash_lock);
      (void)PL_HashTableRemove(oid_hash_table, &rv->data);
      (void)PZ_Unlock(oid_hash_lock);
      goto loser;
    }
  }
#endif /* DEBUG */

  return rv;

 loser:
  if( (NSSOID *)NULL != candidate ) {
    (void)nss_ZFreeIf(candidate->data.data);
  }
  (void)nss_ZFreeIf(candidate);

  if( (NSSOID *)NULL != rv ) {
    (void)nss_ZFreeIf(rv->data.data);
  }
  (void)nss_ZFreeIf(rv);

  return (NSSOID *)NULL;
}

Here is the caller graph for this function:

NSS_EXTERN NSSDER* NSSOID_GetDEREncoding ( const NSSOID *  oid,
NSSDER rvOpt,
NSSArena *  arenaOpt 
)

Definition at line 196 of file oid.c.

{
  nss_ClearErrorStack();

#ifdef DEBUG
  if( PR_SUCCESS != nssOID_verifyPointer(oid) ) {
    return (NSSDER *)NULL;
  }

  if( (NSSArena *)NULL != arenaOpt ) {
    if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
      return (NSSDER *)NULL;
    }
  }
#endif /* DEBUG */

  return nssOID_GetDEREncoding(oid, rvOpt, arenaOpt);
}
NSS_EXTERN NSSDER* nssOID_GetDEREncoding ( const NSSOID *  oid,
NSSDER rvOpt,
NSSArena *  arenaOpt 
)

Definition at line 1220 of file oid.c.

{
  const NSSItem *it;
  NSSDER *rv;

  if( PR_SUCCESS != oid_init() ) {
    return (NSSDER *)NULL;
  }

#ifdef NSSDEBUG
  if( PR_SUCCESS != nssOID_verifyPointer(oid) ) {
    return (NSSDER *)NULL;
  }

  if( (NSSArena *)NULL != arenaOpt ) {
    if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
      return (NSSDER *)NULL;
    }
  }
#endif /* NSSDEBUG */

  it = &oid->data;

  if( (NSSDER *)NULL == rvOpt ) {
    rv = nss_ZNEW(arenaOpt, NSSDER);
    if( (NSSDER *)NULL == rv ) {
      return (NSSDER *)NULL;
    }
  } else {
    rv = rvOpt;
  }

  rv->data = nss_ZAlloc(arenaOpt, it->size);
  if( (void *)NULL == rv->data ) {
    if( rv != rvOpt ) {
      (void)nss_ZFreeIf(rv);
    }
    return (NSSDER *)NULL;
  }

  rv->size = it->size;
  nsslibc_memcpy(rv->data, it->data, it->size);

  return rv;
}

Here is the caller graph for this function:

NSS_EXTERN NSSUTF8* NSSOID_GetUTF8Encoding ( const NSSOID *  oid,
NSSArena *  arenaOpt 
)

Definition at line 241 of file oid.c.

{
  nss_ClearErrorStack();

#ifdef DEBUG
  if( PR_SUCCESS != nssOID_verifyPointer(oid) ) {
    return (NSSUTF8 *)NULL;
  }

  if( (NSSArena *)NULL != arenaOpt ) {
    if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
      return (NSSUTF8 *)NULL;
    }
  }
#endif /* DEBUG */

  return nssOID_GetUTF8Encoding(oid, arenaOpt);
}
NSS_EXTERN NSSUTF8* nssOID_GetUTF8Encoding ( const NSSOID *  oid,
NSSArena *  arenaOpt 
)

Definition at line 1292 of file oid.c.

{
  NSSUTF8 *rv;
  PRUint8 *end;
  PRUint8 *d;
  PRUint8 *e;
  char *a;
  char *b;
  PRUint32 len;

  if( PR_SUCCESS != oid_init() ) {
    return (NSSUTF8 *)NULL;
  }

#ifdef NSSDEBUG
  if( PR_SUCCESS != nssOID_verifyPointer(oid) ) {
    return (NSSUTF8 *)NULL;
  }

  if( (NSSArena *)NULL != arenaOpt ) {
    if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
      return (NSSUTF8 *)NULL;
    }
  }
#endif /* NSSDEBUG */

  a = (char *)NULL;

  /* d will point to the next sequence of bytes to decode */
  d = (PRUint8 *)oid->data.data;
  /* end points to one past the legitimate data */
  end = &d[ oid->data.size ];

#ifdef NSSDEBUG
  /*
   * Guarantee that the for(e=d;e<end;e++) loop below will
   * terminate.  Our BER sanity-checking code above will prevent
   * such a BER from being registered, so the only other way one
   * might show up is if our dotted-decimal encoder above screws
   * up or our generated list is wrong.  So I'll wrap it with
   * #ifdef NSSDEBUG and #endif.
   */
  if( end[-1] & 0x80 ) {
    nss_SetError(NSS_ERROR_INTERNAL_ERROR);
    return (NSSUTF8 *)NULL;
  }
#endif /* NSSDEBUG */

  /*
   * Check for our pseudo-encoded single-digit OIDs
   */
  if( (*d == 0x80) && (2 == oid->data.size) ) {
    /* Funky encoding.  The second byte is the number */
    a = PR_smprintf("%lu", (PRUint32)d[1]);
    if( (char *)NULL == a ) {
      nss_SetError(NSS_ERROR_NO_MEMORY);
      return (NSSUTF8 *)NULL;
    }
    goto done;
  }

  for( ; d < end; d = &e[1] ) {
    
    for( e = d; e < end; e++ ) {
      if( 0 == (*e & 0x80) ) {
        break;
      }
    }
    
    if( ((e-d) > 4) || (((e-d) == 4) && (*d & 0x70)) ) {
      /* More than a 32-bit number */
    } else {
      PRUint32 n = 0;
      
      switch( e-d ) {
      case 4:
        n |= ((PRUint32)(e[-4] & 0x0f)) << 28;
      case 3:
        n |= ((PRUint32)(e[-3] & 0x7f)) << 21;
      case 2:
        n |= ((PRUint32)(e[-2] & 0x7f)) << 14;
      case 1:
        n |= ((PRUint32)(e[-1] & 0x7f)) <<  7;
      case 0:
        n |= ((PRUint32)(e[-0] & 0x7f))      ;
      }
      
      if( (char *)NULL == a ) {
        /* This is the first number.. decompose it */
        PRUint32 one = (n/40), two = (n%40);
        
        a = PR_smprintf("%lu.%lu", one, two);
        if( (char *)NULL == a ) {
          nss_SetError(NSS_ERROR_NO_MEMORY);
          return (NSSUTF8 *)NULL;
        }
      } else {
        b = PR_smprintf("%s.%lu", a, n);
        if( (char *)NULL == b ) {
          PR_smprintf_free(a);
          nss_SetError(NSS_ERROR_NO_MEMORY);
          return (NSSUTF8 *)NULL;
        }
        
        PR_smprintf_free(a);
        a = b;
      }
    }
  }

 done:
  /*
   * Even if arenaOpt is NULL, we have to copy the data so that
   * it'll be freed with the right version of free: ours, not
   * PR_smprintf_free's.
   */
  len = PL_strlen(a);
  rv = (NSSUTF8 *)nss_ZAlloc(arenaOpt, len);
  if( (NSSUTF8 *)NULL == rv ) {
    PR_smprintf_free(a);
    return (NSSUTF8 *)NULL;
  }

  nsslibc_memcpy(rv, a, len);
  PR_smprintf_free(a);

  return rv;
}

Here is the caller graph for this function:

static PRUint32 oid_encode_huge ( NSSUTF8 s,
NSSUTF8 e,
PRUint8 dp,
PRUint32  nb 
) [static]

Definition at line 840 of file oid.c.

{
  PRUint32 slen = (e-s);
  PRUint32 blen = (slen+1)/2;
  PRUint8 *st = (PRUint8 *)NULL;
  PRUint8 *bd = (PRUint8 *)NULL;
  PRUint32 i;
  PRUint32 bitno;
  PRUint8 *last;
  PRUint8 *first;
  PRUint32 byteno;
  PRUint8 mask;

  /* We'll be munging the data, so duplicate it */
  st = (PRUint8 *)nss_ZAlloc((NSSArena *)NULL, slen);
  if( (PRUint8 *)NULL == st ) {
    return 0;
  }

  /* Don't know ahead of time exactly how long we'll need */
  bd = (PRUint8 *)nss_ZAlloc((NSSArena *)NULL, blen);
  if( (PRUint8 *)NULL == bd ) {
    (void)nss_ZFreeIf(st);
    return 0;
  }

  /* Copy the original, and convert ASCII to numbers */
  for( i = 0; i < slen; i++ ) {
    st[i] = (PRUint8)(s[i] - '0');
  }

  last = &st[slen-1];
  first = &st[0];

  /*
   * The way we create the binary version is by looking at it 
   * bit by bit.  Start with the least significant bit.  If the
   * number is odd, set that bit.  Halve the number (with integer
   * division), and go to the next least significant bit.  Keep 
   * going until the number goes to zero.
   */
  for( bitno = 0; ; bitno++ ) {
    PRUint8 *d;

    byteno = bitno/7;
    mask = (PRUint8)(1 << (bitno%7));

    /* Skip leading zeroes */
    for( ; first < last; first ++ ) {
      if( 0 != *first ) {
        break;
      }
    }

    /* Down to one number and it's a zero?  Done. */
    if( (first == last) && (0 == *last) ) {
      break;
    }

    /* Last digit is odd?  Set the bit */
    if( *last & 1 ) {
      bd[ byteno ] |= mask;
    }


    /* 
     * Divide the number in half.  This is just a matter
     * of going from the least significant digit upwards,
     * halving each one.  If any digit is odd (other than
     * the last, which has already been handled), add five
     * to the digit to its right.
     */
    *last /= 2;

    for( d = &last[-1]; d >= first; d-- ) {
      if( *d & 1 ) {
        d[1] += 5;
      }

      *d /= 2;
    }
  }

  /* Is there room to write the encoded data? */
  if( (byteno+1) > nb ) {
    return (byteno+1);
  }

  /* Trim any leading zero that crept in there */
  for( ; byteno > 0; byteno-- ) {
    if( 0 != bd[ byteno ] ) {
      break;
    }
  }

  /* Copy all but the last, marking the "continue" bit */
  for( i = 0; i < byteno; i++ ) {
    dp[i] = bd[ byteno-i ] | 0x80;
  }
  /* And the last with the "continue" bit clear */
  dp[byteno] = bd[0];

  (void)nss_ZFreeIf(bd);
  (void)nss_ZFreeIf(st);
  return (byteno+1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRUint32 oid_encode_number ( PRUint32  n,
PRUint8 dp,
PRUint32  nb 
) [static]

Definition at line 787 of file oid.c.

{
  PRUint32 a[5];
  PRUint32 i;
  PRUint32 rv;

  a[0] = (n >> 28) & 0x7f;
  a[1] = (n >> 21) & 0x7f;
  a[2] = (n >> 14) & 0x7f;
  a[3] = (n >>  7) & 0x7f;
  a[4] =  n        & 0x7f;

  for( i = 0; i < 5; i++ ) {
    if( 0 != a[i] ) {
      break;
    }
  }

  if( 5 == i ) {
    i--;
  }

  rv = 5-i;
  if( rv > nb ) {
    return rv;
  }

  for( ; i < 4; i++ ) {
    *dp = 0x80 | a[i];
    dp++;
  }

  *dp = a[4];

  return rv;
}

Here is the caller graph for this function:

static NSSOID* oid_encode_string ( NSSUTF8 s) [static]

Definition at line 963 of file oid.c.

{
  PRUint32 nn = 0; /* number of numbers */
  PRUint32 nb = 0; /* number of bytes (estimated) */
  NSSUTF8 *t;
  PRUint32 nd = 0; /* number of digits */
  NSSOID *rv;
  PRUint8 *dp;
  PRUint32 a, b;
  PRUint32 inc;

  /* Dump any octothorpe */
  if( '#' == *s ) {
    s++;
  }

  /* Count up the bytes needed */
  for( t = s; '\0' != *t; t++ ) {
    if( '.' == *t ) {
      nb += (nd+1)/2; /* errs on the big side */
      nd = 0;
      nn++;
    } else {
      nd++;
    }
  }
  nb += (nd+1)/2;
  nn++;

  if( 1 == nn ) {
    /*
     * We have our own "denormalised" encoding for these,
     * which is only used internally.
     */
    nb++;
  }

  /* 
   * Allocate.  Note that we don't use the oid_arena here.. this is
   * because there really isn't a "free()" for stuff allocated out of
   * arenas (at least with the current implementation), so this would
   * keep using up memory each time a UTF8-encoded OID were added.
   * If need be (if this is the first time this oid has been seen),
   * we'll copy it.
   */
  rv = nss_ZNEW((NSSArena *)NULL, NSSOID);
  if( (NSSOID *)NULL == rv ) {
    return (NSSOID *)NULL;
  }

  rv->data.data = nss_ZAlloc((NSSArena *)NULL, nb);
  if( (void *)NULL == rv->data.data ) {
    (void)nss_ZFreeIf(rv);
    return (NSSOID *)NULL;
  }

  dp = (PRUint8 *)rv->data.data;

  a = atoi(s);

  if( 1 == nn ) {
    dp[0] = '\x80';
    inc = oid_encode_number(a, &dp[1], nb-1);
    if( inc >= nb ) {
      goto loser;
    }
  } else {
    for( t = s; '.' != *t; t++ ) {
      ;
    }

    t++;
    b = atoi(t);
    inc = oid_encode_number(a*40+b, dp, nb);
    if( inc > nb ) {
      goto loser;
    }
    dp += inc;
    nb -= inc;
    nn -= 2;

    while( nn-- > 0 ) {
      NSSUTF8 *u;

      for( ; '.' != *t; t++ ) {
        ;
      }

      t++;

      for( u = t; ('\0' != *u) && ('.' != *u); u++ ) {
        ;
      }

      if( (u-t > 9) ) {
        /* In the billions.  Rats. */
        inc = oid_encode_huge(t, u, dp, nb);
      } else {
        b = atoi(t);
        inc = oid_encode_number(b, dp, nb);
      }

      if( inc > nb ) {
        goto loser;
      }
      dp += inc;
      nb -= inc;
    }
  }

  return rv;

 loser:
  nss_SetError(NSS_ERROR_INTERNAL_ERROR);
  return (NSSOID *)NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PLHashNumber PR_CALLBACK oid_hash ( const void key) [static]

Definition at line 290 of file oid.c.

{
  const NSSItem *item = (const NSSItem *)key;
  PLHashNumber rv = 0;

  PRUint8 *data = (PRUint8 *)item->data;
  PRUint32 i;
  PRUint8 *rvc = (PRUint8 *)&rv;

  for( i = 0; i < item->size; i++ ) {
    rvc[ i % sizeof(rv) ] ^= *data;
    data++;
  }

  return rv;
}

Here is the caller graph for this function:

static PRIntn PR_CALLBACK oid_hash_compare ( const void k1,
const void k2 
) [static]

Definition at line 318 of file oid.c.

{
  PRIntn rv;

  const NSSItem *i1 = (const NSSItem *)k1;
  const NSSItem *i2 = (const NSSItem *)k2;

  PRUint32 size = (i1->size < i2->size) ? i1->size : i2->size;

  rv = (PRIntn)nsslibc_memequal(i1->data, i2->data, size, (PRStatus *)NULL);
  if( 0 == rv ) {
    rv = i1->size - i2->size;
  }

  return !rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRStatus oid_init ( void  ) [static]

Definition at line 494 of file oid.c.

{
  return PR_CallOnce(&oid_call_once, oid_once_func);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRStatus PR_CALLBACK oid_once_func ( void  ) [static]

Definition at line 415 of file oid.c.

{
  PRUint32 i;
  
  /* Initialize the arena */
  oid_arena = nssArena_Create();
  if( (NSSArena *)NULL == oid_arena ) {
    goto loser;
  }

  /* Create the hash table lock */
  oid_hash_lock = PZ_NewLock(nssILockOID);
  if( (PZLock *)NULL == oid_hash_lock ) {
    nss_SetError(NSS_ERROR_NO_MEMORY);
    goto loser;
  }

  /* Create the hash table */
  oid_hash_table = PL_NewHashTable(0, oid_hash, oid_hash_compare,
                                   PL_CompareValues, 
                                   (PLHashAllocOps *)0,
                                   (void *)0);
  if( (PLHashTable *)NULL == oid_hash_table ) {
    nss_SetError(NSS_ERROR_NO_MEMORY);
    goto loser;
  }

  /* And populate it with all the builtins */
  for( i = 0; i < nss_builtin_oid_count; i++ ) {
    NSSOID *oid = (NSSOID *)&nss_builtin_oids[i];
    PLHashEntry *e = PL_HashTableAdd(oid_hash_table, &oid->data, oid);
    if( (PLHashEntry *)NULL == e ) {
      nss_SetError(NSS_ERROR_NO_MEMORY);
      goto loser;
    }

#ifdef DEBUG
    if( PR_SUCCESS != oid_add_pointer(oid) ) {
      goto loser;
    }
#endif /* DEBUG */
  }

  return PR_SUCCESS;

 loser:
  if( (PLHashTable *)NULL != oid_hash_table ) {
    PL_HashTableDestroy(oid_hash_table);
    oid_hash_table = (PLHashTable *)NULL;
  }

  if( (PZLock *)NULL != oid_hash_lock ) {
    PZ_DestroyLock(oid_hash_lock);
    oid_hash_lock = (PZLock *)NULL;
  }

  if( (NSSArena *)NULL != oid_arena ) {
    (void)nssArena_Destroy(oid_arena);
    oid_arena = (NSSArena *)NULL;
  }

  return PR_FAILURE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRStatus oid_sanity_check_ber ( NSSBER berOid) [static]

Definition at line 558 of file oid.c.

{
  PRUint32 i;
  PRUint8 *data = (PRUint8 *)berOid->data;

  /*
   * The size must be longer than zero bytes.
   */

  if( berOid->size <= 0 ) {
    return PR_FAILURE;
  }

  /*
   * In general, we can't preclude any number from showing up
   * someday.  We could probably guess that top-level numbers
   * won't get very big (beyond the current ccitt(0), iso(1),
   * or joint-ccitt-iso(2)).  However, keep in mind that the
   * encoding rules wrap the first two numbers together, as
   *
   *     (first * 40) + second
   *
   * Also, it is noted in the specs that this implies that the
   * second number won't go above forty.
   *
   * 128 encodes 3.8, which seems pretty safe for now.  Let's
   * check that the first byte is less than that.
   *
   * XXX This is a "soft check" -- we may want to exclude it.
   */

  if( data[0] >= 0x80 ) {
    return PR_FAILURE;
  }

  /*
   * In a normalised format, leading 0x80s will never show up.
   * This means that no 0x80 will be preceeded by the final
   * byte of a sequence, which would naturaly be less than 0x80.
   * Our internal encoding for the single-digit OIDs uses 0x80,
   * but the only places we use them (loading the builtin table,
   * and adding a UTF8-encoded OID) bypass this check.
   */

  for( i = 1; i < berOid->size; i++ ) {
    if( (0x80 == data[i]) && (data[i-1] < 0x80) ) {
      return PR_FAILURE;
    }
  }

  /*
   * The high bit of each octet indicates that following octets
   * are included in the current number.  Thus the last byte can't
   * have the high bit set.
   */

  if( data[ berOid->size-1 ] >= 0x80 ) {
    return PR_FAILURE;
  }

  /*
   * Other than that, any byte sequence is legit.
   */
  return PR_SUCCESS;
}

Here is the caller graph for this function:

static PRStatus oid_sanity_check_utf8 ( NSSUTF8 s) [static]

Definition at line 729 of file oid.c.

{
  /*
   * It may begin with an octothorpe, which we skip.
   */

  if( '#' == *s ) {
    s++;
  }

  /*
   * It begins with a number
   */

  if( (*s < '0') || (*s > '9') ) {
    return PR_FAILURE;
  }

  /*
   * First number is only one digit long
   *
   * XXX This is a "soft check" -- we may want to exclude it
   */

  if( (s[1] != '.') && (s[1] != '\0') ) {
    return PR_FAILURE;
  }

  /*
   * Every character is either a digit or a period
   */

  for( ; '\0' != *s; s++ ) {
    if( ('.' != *s) && ((*s < '0') || (*s > '9')) ) {
      return PR_FAILURE;
    }

    /* No two consecutive periods */
    if( ('.' == *s) && ('.' == s[1]) ) {
      return PR_FAILURE;
    }
  }

  /*
   * The last character isn't a period
   */

  if( '.' == *--s ) {
    return PR_FAILURE;
  }

  return PR_SUCCESS;
}

Here is the caller graph for this function:


Variable Documentation

Definition at line 52 of file errorval.c.

const NSSOID* NSS_OID_UNKNOWN = (NSSOID *)NULL

Definition at line 86 of file oid.c.

NSSArena* oid_arena [static]

Definition at line 405 of file oid.c.

Definition at line 485 of file oid.c.

PZLock* oid_hash_lock [static]

Definition at line 279 of file oid.c.

Definition at line 273 of file oid.c.