/** * gnutls_x509_dn_get_rdn_ava: * @dn: a pointer to DN * @irdn: index of RDN * @iava: index of AVA. * @ava: Pointer to structure which will hold output information. * * Get pointers to data within the DN. The format of the @ava structure * is shown below. * * struct gnutls_x509_ava_st { * gnutls_datum_t oid; * gnutls_datum_t value; * unsigned long value_tag; * }; * * The X.509 distinguished name is a sequence of sequences of strings * and this is what the @irdn and @iava indexes model. * * Note that @ava will contain pointers into the @dn structure which * in turns points to the original certificate. Thus you should not * modify any data or deallocate any of those. * * This is a low-level function that requires the caller to do the * value conversions when necessary (e.g. from UCS-2). * * Returns: Returns 0 on success, or an error code. **/ int gnutls_x509_dn_get_rdn_ava(gnutls_x509_dn_t dn, int irdn, int iava, gnutls_x509_ava_st * ava) { ASN1_TYPE rdn, elem; ASN1_DATA_NODE vnode; long len; int lenlen, remlen, ret; char rbuf[MAX_NAME_SIZE]; unsigned char cls; const unsigned char *ptr; iava++; irdn++; /* 0->1, 1->2 etc */ snprintf(rbuf, sizeof(rbuf), "rdnSequence.?%d.?%d", irdn, iava); rdn = asn1_find_node(dn->asn, rbuf); if (!rdn) { gnutls_assert(); return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND; } snprintf(rbuf, sizeof(rbuf), "?%d.type", iava); elem = asn1_find_node(rdn, rbuf); if (!elem) { gnutls_assert(); return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND; } ret = asn1_read_node_value(elem, &vnode); if (ret != ASN1_SUCCESS) { gnutls_assert(); return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND; } ava->oid.data = (void *) vnode.value; ava->oid.size = vnode.value_len; snprintf(rbuf, sizeof(rbuf), "?%d.value", iava); elem = asn1_find_node(rdn, rbuf); if (!elem) { gnutls_assert(); return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND; } ret = asn1_read_node_value(elem, &vnode); if (ret != ASN1_SUCCESS) { gnutls_assert(); return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND; } /* The value still has the previous tag's length bytes, plus the * current value's tag and length bytes. Decode them. */ ptr = vnode.value; remlen = vnode.value_len; len = asn1_get_length_der(ptr, remlen, &lenlen); if (len < 0) { gnutls_assert(); return GNUTLS_E_ASN1_DER_ERROR; } ptr += lenlen; remlen -= lenlen; ret = asn1_get_tag_der(ptr, remlen, &cls, &lenlen, &ava->value_tag); if (ret) { gnutls_assert(); return _gnutls_asn2err(ret); } ptr += lenlen; remlen -= lenlen; { signed long tmp; tmp = asn1_get_length_der(ptr, remlen, &lenlen); if (tmp < 0) { gnutls_assert(); return GNUTLS_E_ASN1_DER_ERROR; } ava->value.size = tmp; } ava->value.data = (void *) (ptr + lenlen); return 0; }
/** * asn1_print_structure: * @out: pointer to the output file (e.g. stdout). * @structure: pointer to the structure that you want to visit. * @name: an element of the structure * @mode: specify how much of the structure to print, can be * %ASN1_PRINT_NAME, %ASN1_PRINT_NAME_TYPE, * %ASN1_PRINT_NAME_TYPE_VALUE, or %ASN1_PRINT_ALL. * * Prints on the @out file descriptor the structure's tree starting * from the @name element inside the structure @structure. **/ void asn1_print_structure (FILE * out, ASN1_TYPE structure, const char *name, int mode) { ASN1_TYPE p, root; int k, indent = 0, len, len2, len3; if (out == NULL) return; root = asn1_find_node (structure, name); if (root == NULL) return; p = root; while (p) { if (mode == ASN1_PRINT_ALL) { for (k = 0; k < indent; k++) fprintf (out, " "); fprintf (out, "name:"); if (p->name) fprintf (out, "%s ", p->name); else fprintf (out, "NULL "); } else { switch (type_field (p->type)) { case TYPE_CONSTANT: case TYPE_TAG: case TYPE_SIZE: break; default: for (k = 0; k < indent; k++) fprintf (out, " "); fprintf (out, "name:"); if (p->name) fprintf (out, "%s ", p->name); else fprintf (out, "NULL "); } } if (mode != ASN1_PRINT_NAME) { switch (type_field (p->type)) { case TYPE_CONSTANT: if (mode == ASN1_PRINT_ALL) fprintf (out, "type:CONST"); break; case TYPE_TAG: if (mode == ASN1_PRINT_ALL) fprintf (out, "type:TAG"); break; case TYPE_SIZE: if (mode == ASN1_PRINT_ALL) fprintf (out, "type:SIZE"); break; case TYPE_DEFAULT: fprintf (out, "type:DEFAULT"); break; case TYPE_NULL: fprintf (out, "type:NULL"); break; case TYPE_IDENTIFIER: fprintf (out, "type:IDENTIFIER"); break; case TYPE_INTEGER: fprintf (out, "type:INTEGER"); break; case TYPE_ENUMERATED: fprintf (out, "type:ENUMERATED"); break; case TYPE_TIME: fprintf (out, "type:TIME"); break; case TYPE_BOOLEAN: fprintf (out, "type:BOOLEAN"); break; case TYPE_SEQUENCE: fprintf (out, "type:SEQUENCE"); break; case TYPE_BIT_STRING: fprintf (out, "type:BIT_STR"); break; case TYPE_OCTET_STRING: fprintf (out, "type:OCT_STR"); break; case TYPE_GENERALSTRING: fprintf (out, "type:GENERALSTRING"); break; case TYPE_SEQUENCE_OF: fprintf (out, "type:SEQ_OF"); break; case TYPE_OBJECT_ID: fprintf (out, "type:OBJ_ID"); break; case TYPE_ANY: fprintf (out, "type:ANY"); break; case TYPE_SET: fprintf (out, "type:SET"); break; case TYPE_SET_OF: fprintf (out, "type:SET_OF"); break; case TYPE_CHOICE: fprintf (out, "type:CHOICE"); break; case TYPE_DEFINITIONS: fprintf (out, "type:DEFINITIONS"); break; default: break; } } if ((mode == ASN1_PRINT_NAME_TYPE_VALUE) || (mode == ASN1_PRINT_ALL)) { switch (type_field (p->type)) { case TYPE_CONSTANT: if (mode == ASN1_PRINT_ALL) if (p->value) fprintf (out, " value:%s", p->value); break; case TYPE_TAG: if (mode == ASN1_PRINT_ALL) if (p->value) fprintf (out, " value:%s", p->value); break; case TYPE_SIZE: if (mode == ASN1_PRINT_ALL) if (p->value) fprintf (out, " value:%s", p->value); break; case TYPE_DEFAULT: if (p->value) fprintf (out, " value:%s", p->value); else if (p->type & CONST_TRUE) fprintf (out, " value:TRUE"); else if (p->type & CONST_FALSE) fprintf (out, " value:FALSE"); break; case TYPE_IDENTIFIER: if (p->value) fprintf (out, " value:%s", p->value); break; case TYPE_INTEGER: if (p->value) { len2 = -1; len = asn1_get_length_der (p->value, p->value_len, &len2); fprintf (out, " value:0x"); if (len > 0) for (k = 0; k < len; k++) fprintf (out, "%02x", (p->value)[k + len2]); } break; case TYPE_ENUMERATED: if (p->value) { len2 = -1; len = asn1_get_length_der (p->value, p->value_len, &len2); fprintf (out, " value:0x"); if (len > 0) for (k = 0; k < len; k++) fprintf (out, "%02x", (p->value)[k + len2]); } break; case TYPE_TIME: if (p->value) fprintf (out, " value:%s", p->value); break; case TYPE_BOOLEAN: if (p->value) { if (p->value[0] == 'T') fprintf (out, " value:TRUE"); else if (p->value[0] == 'F') fprintf (out, " value:FALSE"); } break; case TYPE_BIT_STRING: if (p->value) { len2 = -1; len = asn1_get_length_der (p->value, p->value_len, &len2); if (len > 0) { fprintf (out, " value(%i):", (len - 1) * 8 - (p->value[len2])); for (k = 1; k < len; k++) fprintf (out, "%02x", (p->value)[k + len2]); } } break; case TYPE_OCTET_STRING: if (p->value) { len2 = -1; len = asn1_get_length_der (p->value, p->value_len, &len2); fprintf (out, " value:"); if (len > 0) for (k = 0; k < len; k++) fprintf (out, "%02x", (p->value)[k + len2]); } break; case TYPE_GENERALSTRING: if (p->value) { len2 = -1; len = asn1_get_length_der (p->value, p->value_len, &len2); fprintf (out, " value:"); if (len > 0) for (k = 0; k < len; k++) fprintf (out, "%02x", (p->value)[k + len2]); } break; case TYPE_OBJECT_ID: if (p->value) fprintf (out, " value:%s", p->value); break; case TYPE_ANY: if (p->value) { len3 = -1; len2 = asn1_get_length_der (p->value, p->value_len, &len3); fprintf (out, " value:"); if (len2 > 0) for (k = 0; k < len2; k++) fprintf (out, "%02x", (p->value)[k + len3]); } break; case TYPE_SET: case TYPE_SET_OF: case TYPE_CHOICE: case TYPE_DEFINITIONS: case TYPE_SEQUENCE_OF: case TYPE_SEQUENCE: case TYPE_NULL: break; default: break; } } if (mode == ASN1_PRINT_ALL) { if (p->type & 0x1FFFFF00) { fprintf (out, " attr:"); if (p->type & CONST_UNIVERSAL) fprintf (out, "UNIVERSAL,"); if (p->type & CONST_PRIVATE) fprintf (out, "PRIVATE,"); if (p->type & CONST_APPLICATION) fprintf (out, "APPLICATION,"); if (p->type & CONST_EXPLICIT) fprintf (out, "EXPLICIT,"); if (p->type & CONST_IMPLICIT) fprintf (out, "IMPLICIT,"); if (p->type & CONST_TAG) fprintf (out, "TAG,"); if (p->type & CONST_DEFAULT) fprintf (out, "DEFAULT,"); if (p->type & CONST_TRUE) fprintf (out, "TRUE,"); if (p->type & CONST_FALSE) fprintf (out, "FALSE,"); if (p->type & CONST_LIST) fprintf (out, "LIST,"); if (p->type & CONST_MIN_MAX) fprintf (out, "MIN_MAX,"); if (p->type & CONST_OPTION) fprintf (out, "OPTION,"); if (p->type & CONST_1_PARAM) fprintf (out, "1_PARAM,"); if (p->type & CONST_SIZE) fprintf (out, "SIZE,"); if (p->type & CONST_DEFINED_BY) fprintf (out, "DEF_BY,"); if (p->type & CONST_GENERALIZED) fprintf (out, "GENERALIZED,"); if (p->type & CONST_UTC) fprintf (out, "UTC,"); if (p->type & CONST_SET) fprintf (out, "SET,"); if (p->type & CONST_NOT_USED) fprintf (out, "NOT_USED,"); if (p->type & CONST_ASSIGN) fprintf (out, "ASSIGNMENT,"); } } if (mode == ASN1_PRINT_ALL) { fprintf (out, "\n"); } else { switch (type_field (p->type)) { case TYPE_CONSTANT: case TYPE_TAG: case TYPE_SIZE: break; default: fprintf (out, "\n"); } } if (p->down) { p = p->down; indent += 2; } else if (p == root) { p = NULL; break; } else if (p->right) p = p->right; else { while (1) { p = _asn1_find_up (p); if (p == root) { p = NULL; break; } indent -= 2; if (p->right) { p = p->right; break; } } } } }
int main (int argc, char **argv) { /* Test that values larger than long are rejected. This has worked fine with all versions of libtasn1. */ int verbose = 0; if (argc > 1) verbose = 1; { unsigned char der[] = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"; long l; int len; l = asn1_get_length_der (der, sizeof der, &len); if (l == -2L) { if (verbose) puts ("OK: asn1_get_length_der bignum"); } else { printf ("ERROR: asn1_get_length_der bignum (l %ld len %d)\n", l, len); return 1; } } /* Test that values larger than int but smaller than long are rejected. This limitation was introduced with libtasn1 2.12. */ if (LONG_MAX > INT_MAX) { unsigned long num = ((long) UINT_MAX) << 2; unsigned char der[20]; int der_len; long l; int len; asn1_length_der (num, der, &der_len); l = asn1_get_length_der (der, der_len, &len); if (l == -2L) { if (verbose) puts ("OK: asn1_get_length_der intnum"); } else { printf ("ERROR: asn1_get_length_der intnum (l %ld len %d)\n", l, len); return 1; } } /* Test that values larger than would fit in the input string are rejected. This problem was fixed in libtasn1 2.12. */ { unsigned long num = 64; unsigned char der[20]; int der_len; long l; int len; asn1_length_der (num, der, &der_len); der_len = sizeof (der); l = asn1_get_length_der (der, der_len, &len); if (l == -4L) { if (verbose) puts ("OK: asn1_get_length_der overflow-small"); } else { printf ("ERROR: asn1_get_length_der overflow-small (l %ld len %d)\n", l, len); return 1; } } /* Test that values larger than would fit in the input string are rejected. This problem was fixed in libtasn1 2.12. */ { unsigned long num = 1073741824; unsigned char der[20]; int der_len; long l; int len; asn1_length_der (num, der, &der_len); der_len = sizeof (der); l = asn1_get_length_der (der, der_len, &len); if (l == -4L) { if (verbose) puts ("OK: asn1_get_length_der overflow-large1"); } else { printf ("ERROR: asn1_get_length_der overflow-large1 (l %ld len %d)\n", l, len); return 1; } } /* Test that values larger than would fit in the input string are rejected. This problem was fixed in libtasn1 2.12. */ { unsigned long num = 2147483649; unsigned char der[20]; int der_len; long l; int len; asn1_length_der (num, der, &der_len); der_len = sizeof (der); l = asn1_get_length_der (der, der_len, &len); if (l == -2L) { if (verbose) puts ("OK: asn1_get_length_der overflow-large2"); } else { printf ("ERROR: asn1_get_length_der overflow-large2 (l %ld len %d)\n", l, len); return 1; } } return 0; }