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 + -
显示快捷键?