atav.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,804 行 · 第 1/3 页

C
1,804
字号
static PRStatusatav_remove_pointer(  const NSSATAV *atav){  PRStatus rv;  rv = nssPointerTracker_remove(&atav_pointer_tracker, atav);  if( PR_SUCCESS != rv ) {    nss_SetError(NSS_ERROR_INTERNAL_ERROR);  }  return rv;}/* * nssATAV_verifyPointer * * This method is only present in debug builds. * * If the specified pointer is a valid pointer to an NSSATAV object, * this routine will return PR_SUCCESS.  Otherwise, it will put an * error on the error stack and return PR_FAILRUE. * * The error may be one of the following values: *  NSS_ERROR_INVALID_NSSATAV *  NSS_ERROR_NO_MEMORY * * Return value: *  PR_SUCCESS if the pointer is valid *  PR_FAILURE if it isn't */NSS_IMPLEMENT PRStatusnssATAV_verifyPointer(  NSSATAV *atav){  PRStatus rv;  rv = nssPointerTracker_initialize(&atav_pointer_tracker);  if( PR_SUCCESS != rv ) {    return PR_FAILURE;  }  rv = nssPointerTracker_verify(&atav_pointer_tracker, atav);  if( PR_SUCCESS != rv ) {    nss_SetError(NSS_ERROR_INVALID_ATAV);    return PR_FAILURE;  }  return PR_SUCCESS;}#endif /* DEBUG */typedef struct {  NSSBER oid;  NSSBER value;} atav_holder;static const nssASN1Template nss_atav_template[] = {  { nssASN1_SEQUENCE, 0, NULL, sizeof(atav_holder) },  { nssASN1_OBJECT_ID, nsslibc_offsetof(atav_holder, oid), NULL, 0 },  { nssASN1_ANY, nsslibc_offsetof(atav_holder, value), NULL, 0 },  { 0, 0, NULL, 0 }};/* * There are several common attributes, with well-known type aliases * and value semantics.  This table lists the ones we recognize. */struct nss_attribute_data_str {  const NSSOID **oid;  nssStringType stringType;  PRUint32 minStringLength;  PRUint32 maxStringLength; /* zero for no limit */};static const struct nss_attribute_data_str nss_attribute_data[] = {  { &NSS_OID_X520_NAME,                         nssStringType_DirectoryString, 1, 32768 },  { &NSS_OID_X520_COMMON_NAME,                  nssStringType_DirectoryString, 1,    64 },  { &NSS_OID_X520_SURNAME,                      nssStringType_DirectoryString, 1,    40 },  { &NSS_OID_X520_GIVEN_NAME,                   nssStringType_DirectoryString, 1,    16 },  { &NSS_OID_X520_INITIALS,                     nssStringType_DirectoryString, 1,     5 },  { &NSS_OID_X520_GENERATION_QUALIFIER,         nssStringType_DirectoryString, 1,     3 },  { &NSS_OID_X520_DN_QUALIFIER,                 nssStringType_PrintableString, 1,     0 },  { &NSS_OID_X520_COUNTRY_NAME,                 nssStringType_PrintableString, 2,     2 },  { &NSS_OID_X520_LOCALITY_NAME,                nssStringType_DirectoryString, 1,   128 },  { &NSS_OID_X520_STATE_OR_PROVINCE_NAME,       nssStringType_DirectoryString, 1,   128 },  { &NSS_OID_X520_ORGANIZATION_NAME,            nssStringType_DirectoryString, 1,    64 },  { &NSS_OID_X520_ORGANIZATIONAL_UNIT_NAME,     nssStringType_DirectoryString, 1,    /*     * Note, draft #11 defines both "32" and "64" for this maximum,     * in two separate places.  Until it's settled, "conservative     * in what you send."  We're always liberal in what we accept.     */                                         32 },  { &NSS_OID_X520_TITLE,                        nssStringType_DirectoryString, 1,    64 },  { &NSS_OID_RFC1274_EMAIL,                     nssStringType_PHGString,       1,   128 }};PRUint32 nss_attribute_data_quantity =   (sizeof(nss_attribute_data)/sizeof(nss_attribute_data[0]));static nssStringTypenss_attr_underlying_string_form(  nssStringType type,  void *data){  if( nssStringType_DirectoryString == type ) {    PRUint8 tag = *(PRUint8 *)data;    switch( tag & nssASN1_TAGNUM_MASK ) {    case 20:      /*       * XXX fgmr-- we have to accept Latin-1 for Teletex; (see       * below) but is T61 a suitable value for "Latin-1"?       */      return nssStringType_TeletexString;    case 19:      return nssStringType_PrintableString;    case 28:      return nssStringType_UniversalString;    case 30:      return nssStringType_BMPString;    case 12:      return nssStringType_UTF8String;    default:      return nssStringType_Unknown;    }  }  return type;}    /* * This routine decodes the attribute value, in a type-specific way. * */static NSSUTF8 *nss_attr_to_utf8(  NSSArena *arenaOpt,  const NSSOID *oid,  NSSItem *item,  nssStringType *stringForm){  NSSUTF8 *rv = (NSSUTF8 *)NULL;  PRUint32 i;  const struct nss_attribute_data_str *which =     (struct nss_attribute_data_str *)NULL;  PRUint32 len = 0;  for( i = 0; i < nss_attribute_data_quantity; i++ ) {    if( *(nss_attribute_data[ i ].oid) == oid ) {      which = &nss_attribute_data[i];      break;    }  }  if( (struct nss_attribute_data_str *)NULL == which ) {    /* Unknown OID.  Encode it as hex. */    PRUint8 *c;    PRUint8 *d = (PRUint8 *)item->data;    PRUint32 amt = item->size;    if( item->size >= 0x7FFFFFFF ) {      nss_SetError(NSS_ERROR_INVALID_STRING);      return (NSSUTF8 *)NULL;    }    len = 1 + (item->size * 2) + 1; /* '#' + hex + '\0' */    rv = (NSSUTF8 *)nss_ZAlloc(arenaOpt, len);    if( (NSSUTF8 *)NULL == rv ) {      return (NSSUTF8 *)NULL;    }    c = (PRUint8 *)rv;    *c++ = '#'; /* XXX fgmr check this */    while( amt > 0 ) {      static char hex[16] = "0123456789ABCDEF";      *c++ = hex[ ((*d) & 0xf0) >> 4 ];      *c++ = hex[ ((*d) & 0x0f)      ];    }    /* *c = '\0'; nss_ZAlloc, remember */    *stringForm = nssStringType_Unknown; /* force exact comparison */  } else {    rv = nssUTF8_CreateFromBER(arenaOpt, which->stringType,                                (NSSBER *)item);    if( (NSSUTF8 *)NULL == rv ) {      return (NSSUTF8 *)NULL;    }    if( PR_SUCCESS != nssUTF8_Length(rv, &len) ) {      nss_ZFreeIf(rv);      return (NSSUTF8 *)NULL;    }    *stringForm = nss_attr_underlying_string_form(which->stringType,                                                  item->data);  }  return rv;}/* * nssATAV_CreateFromBER *  * This routine creates an NSSATAV by decoding a BER- or DER-encoded * ATAV.  If the optional arena argument is non-null, the memory used  * will be obtained from that arena; otherwise, the memory will be  * obtained from the heap.  This routine may return NULL upon error,  * in which case it will have set an error on the error stack. * * The error may be one of the following values: *  NSS_ERROR_INVALID_BER *  NSS_ERROR_NO_MEMORY * * Return value: *  NULL upon error *  A pointer to an NSSATAV upon success */NSS_IMPLEMENT NSSATAV *nssATAV_CreateFromBER(  NSSArena *arenaOpt,  const NSSBER *berATAV){  atav_holder holder;  PRStatus status;  NSSATAV *rv;#ifdef NSSDEBUG  if( (NSSArena *)NULL != arenaOpt ) {    if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {      return (NSSATAV *)NULL;    }  }  /*    * NSSBERs can be created by the user,    * so no pointer-tracking can be checked.   */  if( (NSSBER *)NULL == berATAV ) {    nss_SetError(NSS_ERROR_INVALID_BER);    return (NSSATAV *)NULL;  }  if( (void *)NULL == berATAV->data ) {    nss_SetError(NSS_ERROR_INVALID_BER);    return (NSSATAV *)NULL;  }#endif /* NSSDEBUG */  status = nssASN1_DecodeBER(arenaOpt, &holder,                              nss_atav_template, berATAV);  if( PR_SUCCESS != status ) {    return (NSSATAV *)NULL;  }  rv = nss_ZNEW(arenaOpt, NSSATAV);  if( (NSSATAV *)NULL == rv ) {    nss_ZFreeIf(holder.oid.data);    nss_ZFreeIf(holder.value.data);    return (NSSATAV *)NULL;  }  rv->oid = nssOID_CreateFromBER(&holder.oid);  if( (NSSOID *)NULL == rv->oid ) {    nss_ZFreeIf(rv);    nss_ZFreeIf(holder.oid.data);    nss_ZFreeIf(holder.value.data);    return (NSSATAV *)NULL;  }  nss_ZFreeIf(holder.oid.data);  rv->ber.data = nss_ZAlloc(arenaOpt, berATAV->size);  if( (void *)NULL == rv->ber.data ) {    nss_ZFreeIf(rv);    nss_ZFreeIf(holder.value.data);    return (NSSATAV *)NULL;  }  rv->ber.size = berATAV->size;  (void)nsslibc_memcpy(rv->ber.data, berATAV->data, berATAV->size);  rv->value = nss_attr_to_utf8(arenaOpt, rv->oid, &holder.value,                               &rv->stringForm);  if( (NSSUTF8 *)NULL == rv->value ) {    nss_ZFreeIf(rv->ber.data);    nss_ZFreeIf(rv);    nss_ZFreeIf(holder.value.data);    return (NSSATAV *)NULL;  }  nss_ZFreeIf(holder.value.data);#ifdef DEBUG  if( PR_SUCCESS != atav_add_pointer(rv) ) {    nss_ZFreeIf(rv->ber.data);    nss_ZFreeIf(rv->value);    nss_ZFreeIf(rv);    return (NSSATAV *)NULL;  }#endif /* DEBUG */  return rv;}static PRBoolnss_atav_utf8_string_is_hex(  const NSSUTF8 *s){  /* All hex digits are ASCII, so this works */  PRUint8 *p = (PRUint8 *)s;  for( ; (PRUint8)0 != *p; p++ ) {    if( (('0' <= *p) && (*p <= '9')) ||        (('A' <= *p) && (*p <= 'F')) ||        (('a' <= *p) && (*p <= 'f')) ) {      continue;    } else {      return PR_FALSE;    }  }  return PR_TRUE;}static PRUint8nss_atav_fromhex(  PRUint8 *d){  PRUint8 rv;  if( d[0] <= '9' ) {    rv = (d[0] - '0') * 16;  } else if( d[0] >= 'a' ) {    rv = (d[0] - 'a' + 10) * 16;  } else {    rv = (d[0] - 'A' + 10);  }  if( d[1] <= '9' ) {    rv += (d[1] - '0');  } else if( d[1] >= 'a' ) {    rv += (d[1] - 'a' + 10);  } else {    rv += (d[1] - 'A' + 10);  }  return rv;}/* * nssATAV_CreateFromUTF8 * * This routine creates an NSSATAV by decoding a UTF8 string in the * "equals" format, e.g., "c=US."  If the optional arena argument is  * non-null, the memory used will be obtained from that arena;  * otherwise, the memory will be obtained from the heap.  This routine * may return NULL upon error, in which case it will have set an error  * on the error stack. * * The error may be one of the following values: *  NSS_ERROR_UNKNOWN_ATTRIBUTE *  NSS_ERROR_INVALID_STRING *  NSS_ERROR_NO_MEMORY * * Return value: *  NULL upon error *  A pointer to an NSSATAV upon success */extern const NSSError NSS_ERROR_INTERNAL_ERROR;NSS_IMPLEMENT NSSATAV *nssATAV_CreateFromUTF8(  NSSArena *arenaOpt,  const NSSUTF8 *stringATAV){  char *c;  NSSUTF8 *type;  NSSUTF8 *value;  PRUint32 i;  const NSSOID *oid = (NSSOID *)NULL;  NSSATAV *rv;  NSSItem xitem;  xitem.data = (void *)NULL;  for( c = (char *)stringATAV; '\0' != *c; c++ ) {    if( '=' == *c ) {#ifdef PEDANTIC      /*       * Theoretically, one could have an '=' in an        * attribute string alias.  We don't, yet, though.       */      if( (char *)stringATAV == c ) {        nss_SetError(NSS_ERROR_INVALID_STRING);        return (NSSATAV *)NULL;      } else {        if( '\\' == c[-1] ) {          continue;        }      }#endif /* PEDANTIC */      break;    }  }  if( '\0' == *c ) {    nss_SetError(NSS_ERROR_INVALID_UTF8);    return (NSSATAV *)NULL;  } else {    c++;    value = (NSSUTF8 *)c;  }  i = ((NSSUTF8 *)c - stringATAV);  type = (NSSUTF8 *)nss_ZAlloc((NSSArena *)NULL, i);  if( (NSSUTF8 *)NULL == type ) {    return (NSSATAV *)NULL;  }  (void)nsslibc_memcpy(type, stringATAV, i-1);  c = (char *)stringATAV;  if( (('0' <= *c) && (*c <= '9')) || ('#' == *c) ) {    oid = nssOID_CreateFromUTF8(type);    if( (NSSOID *)NULL == oid ) {      nss_ZFreeIf(type);      return (NSSATAV *)NULL;    }  } else {    for( i = 0; i < nss_attribute_type_alias_count; i++ ) {      const nssAttributeTypeAliasTable *e = &nss_attribute_type_aliases[i];      PRBool match = PR_FALSE;      if( PR_SUCCESS != nssUTF8_CaseIgnoreMatch(type, e->alias,                                                 &match) ) {        nss_ZFreeIf(type);        return (NSSATAV *)NULL;      }      if( PR_TRUE == match ) {        oid = *(e->oid);        break;      }    }    if( (NSSOID *)NULL == oid ) {      nss_ZFreeIf(type);      nss_SetError(NSS_ERROR_UNKNOWN_ATTRIBUTE);      return (NSSATAV *)NULL;    }  }  nss_ZFreeIf(type);  type = (NSSUTF8 *)NULL;  rv = nss_ZNEW(arenaOpt, NSSATAV);  if( (NSSATAV *)NULL == rv ) {    return (NSSATAV *)NULL;  }  rv->oid = oid;  if( '#' == *value ) { /* XXX fgmr.. was it '#'?  or backslash? */    PRUint32 size;    PRUint32 len;    PRUint8 *c;    PRUint8 *d;    /* It's in hex */    value++;    if( PR_TRUE != nss_atav_utf8_string_is_hex(value) ) {      (void)nss_ZFreeIf(rv);      nss_SetError(NSS_ERROR_INVALID_STRING);      return (NSSATAV *)NULL;    }    if( PR_SUCCESS != nssUTF8_Size(value, &size) ) {      /*        * Only returns an error on bad pointer (nope) or string       * too long.  The defined limits for known attributes are       * small enough to fit in PRUint32, and when undefined we       * get to apply our own practical limits.  Ergo, I say the        * string is invalid.       */      (void)nss_ZFreeIf(rv);      nss_SetError(NSS_ERROR_INVALID_STRING);      return (NSSATAV *)NULL;    }    if( ((size-1) & 1) ) {      /* odd length */      (void)nss_ZFreeIf(rv);      nss_SetError(NSS_ERROR_INVALID_STRING);      return (NSSATAV *)NULL;    }    len = (size-1)/2;    rv->value = (NSSUTF8 *)nss_ZAlloc(arenaOpt, len+1);    if( (NSSUTF8 *)NULL == rv->value ) {      (void)nss_ZFreeIf(rv);      return (NSSATAV *)NULL;    }    xitem.size = len;    xitem.data = (void *)rv->value;    for( c = rv->value, d = value; len--; c++, d += 2 ) {      *c = nss_atav_fromhex(d);    }    *c = 0;  } else {    PRUint32 i, len;    PRUint8 *s;    /*     * XXX fgmr-- okay, this is a little wasteful, and should     * probably be abstracted out a bit.  Later.     */    rv->value = nssUTF8_Duplicate(value, arenaOpt);    if( (NSSUTF8 *)NULL == rv->value ) {      (void)nss_ZFreeIf(rv);      return (NSSATAV *)NULL;    }    if( PR_SUCCESS != nssUTF8_Size(rv->value, &len) ) {      (void)nss_ZFreeIf(rv->value);      (void)nss_ZFreeIf(rv);      return (NSSATAV *)NULL;    }    s = (PRUint8 *)rv->value;    for( i = 0; i < len; i++ ) {      if( '\\' == s[i] ) {        (void)nsslibc_memcpy(&s[i], &s[i+1], len-i-1);      }    }  }  /* Now just BER-encode the baby and we're through.. */  {    const struct nss_attribute_data_str *which =       (struct nss_attribute_data_str *)NULL;    PRUint32 i;    NSSArena *a;    NSSDER *oidder;    NSSItem *vitem;    atav_holder ah;    NSSDER *status;    for( i = 0; i < nss_attribute_data_quantity; i++ ) {      if( *(nss_attribute_data[ i ].oid) == rv->oid ) {        which = &nss_attribute_data[i];        break;      }    }    a = NSSArena_Create();    if( (NSSArena *)NULL == a ) {      (void)nss_ZFreeIf(rv->value);      (void)nss_ZFreeIf(rv);      return (NSSATAV *)NULL;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?