--- src/ber-decoder.c +++ src/ber-decoder.c @@ -61,6 +61,19 @@ AsnNode root; /* of the expanded parse tree */ DECODER_STATE ds; int bypass; + + /* Because some certificates actually come with trailing garbage, we + use a hack to ignore this garbage. This hack is enabled for data + starting with a fixed length sequence and this variable takes the + length of this sequence. If it is 0, the hack is not + acticated. */ + unsigned long outer_sequence_length; + int ignore_garbage; /* Set to indicate that garpage should be + ignored. */ + int first_tag_seen; /* Indicates whether the first tag of a decoder + run has been read. */ + + int honor_module_end; int debug; int use_image; @@ -750,7 +763,7 @@ decoder_next (BerDecoder d) { struct tag_info ti; - AsnNode node; + AsnNode node=NULL; gpg_error_t err; DECODER_STATE ds = d->ds; int debug = d->debug; @@ -758,6 +771,17 @@ err = _ksba_ber_read_tl (d->reader, &ti); if (err) { + /* This is our actual hack to cope with some trailing garbage: + Only if we get an premature EOF and we know that we have read + the complete certificate we change the error to EOF. This + won't help with all kinds of garbage but it fixes the case + where just one byte is appended. This is for example the + case with current Siemens certificates. This approach seems + to be the least intrusive one. */ + if (gpg_err_code (err) == GPG_ERR_BAD_BER + && d->ignore_garbage + && ti.err_string && !strcmp (ti.err_string, "premature EOF")) + err = gpg_error (GPG_ERR_EOF); return err; } @@ -770,8 +794,8 @@ { if (!d->image.buf) { - /* we need some extra bytes to store the stuff we read ahead - at the end of the module which is later pushed back */ + /* We need some extra bytes to store the stuff we read ahead + at the end of the module which is later pushed back. */ d->image.length = ti.length + 100; d->image.used = 0; d->image.buf = xtrymalloc (d->image.length); @@ -850,7 +874,14 @@ ds->idx? ds->stack[ds->idx-1].length:-1, ds->cur.nread, ti.is_constructed? "con":"pri"); - + if (d->outer_sequence_length + && ds->idx == 1 + && ds->cur.nread == d->outer_sequence_length) + { + if (debug) + fprintf (stderr, " Need to stop now\n"); + d->ignore_garbage = 1; + } if ( ds->idx && !ds->stack[ds->idx-1].ndef_length && (ds->cur.nread @@ -879,7 +910,7 @@ && (ds->cur.nread >= ds->stack[ds->idx-1].length)); - if (ti.is_constructed) + if (ti.is_constructed && (ti.length || ti.ndef)) { /* prepare for the next level */ ds->cur.length = ti.length; @@ -1084,9 +1115,12 @@ int n, c; node = d->val.node; - if (node && d->use_image) + /* Fixme: USE_IMAGE is only not used with the ber-dump utility + and thus of no big use. We should remove the other code + paths and dump ber-dump.c. */ + if (d->use_image) { - if (!d->val.is_endtag) + if (node && !d->val.is_endtag) { /* We don't have nodes for the end tag - so don't store it */ node->off = (ksba_reader_tell (d->reader) - d->val.nhdr - startoff);