diff options
author | Robin Watts <Robin.Watts@artifex.com> | 2011-06-14 17:00:04 +0100 |
---|---|---|
committer | Robin Watts <Robin.Watts@artifex.com> | 2011-06-14 17:00:04 +0100 |
commit | cbf50e333dc1e80cd968c5ee931b4d6886b116a4 (patch) | |
tree | 03ca5709d081197b76e904947e0e8b570d5b9c6d | |
parent | ff0b19b58d678ee3ed8e8da58dc4e7641e1bb922 (diff) | |
download | mupdf-cbf50e333dc1e80cd968c5ee931b4d6886b116a4.tar.xz |
Fix Bug 692277: PDF file won't open.
Acrobat (and gs, see bug 690478) will open a file without a CF dictionary
by assuming that the encryption type is RC4. Mirror this in mupdf.
-rw-r--r-- | pdf/pdf_crypt.c | 90 |
1 files changed, 49 insertions, 41 deletions
diff --git a/pdf/pdf_crypt.c b/pdf/pdf_crypt.c index f05b7366..5cbe6678 100644 --- a/pdf/pdf_crypt.c +++ b/pdf/pdf_crypt.c @@ -40,7 +40,7 @@ struct pdf_crypt_s unsigned char key[32]; /* decryption key generated from password */ }; -static fz_error pdf_parse_crypt_filter(pdf_crypt_filter *cf, fz_obj *dict, int defaultlength); +static fz_error pdf_parse_crypt_filter(pdf_crypt_filter *cf, fz_obj *dict, char *name, int defaultlength); /* * Create crypt object for decrypting strings and streams @@ -129,43 +129,37 @@ pdf_new_crypt(pdf_crypt **cryptp, fz_obj *dict, fz_obj *id) if (fz_is_dict(obj)) { crypt->cf = fz_keep_obj(obj); + } + else + { + crypt->cf = NULL; + } - obj = fz_dict_gets(dict, "StmF"); - if (fz_is_name(obj)) + obj = fz_dict_gets(dict, "StmF"); + if (fz_is_name(obj)) + { + error = pdf_parse_crypt_filter(&crypt->stmf, crypt->cf, fz_to_name(obj), crypt->length); + if (error) { - /* should verify that it is either Identity or StdCF */ - obj = fz_dict_gets(crypt->cf, fz_to_name(obj)); - if (fz_is_dict(obj)) - { - error = pdf_parse_crypt_filter(&crypt->stmf, obj, crypt->length); - if (error) - { - pdf_free_crypt(crypt); - return fz_rethrow(error, "cannot parse stream crypt filter (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); - } - } + pdf_free_crypt(crypt); + return fz_rethrow(error, "cannot parse stream crypt filter (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); } + } - obj = fz_dict_gets(dict, "StrF"); - if (fz_is_name(obj)) + obj = fz_dict_gets(dict, "StrF"); + if (fz_is_name(obj)) + { + error = pdf_parse_crypt_filter(&crypt->strf, crypt->cf, fz_to_name(obj), crypt->length); + if (error) { - /* should verify that it is either Identity or StdCF */ - obj = fz_dict_gets(crypt->cf, fz_to_name(obj)); - if (fz_is_dict(obj)) - { - error = pdf_parse_crypt_filter(&crypt->strf, obj, crypt->length); - if (error) - { - pdf_free_crypt(crypt); - return fz_rethrow(error, "cannot parse string crypt filter (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); - } - } + pdf_free_crypt(crypt); + return fz_rethrow(error, "cannot parse string crypt filter (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); } - - /* in crypt revision 4, the crypt filter determines the key length */ - if (crypt->strf.method != PDF_CRYPT_NONE) - crypt->length = crypt->stmf.length; } + + /* in crypt revision 4, the crypt filter determines the key length */ + if (crypt->strf.method != PDF_CRYPT_NONE) + crypt->length = crypt->stmf.length; } /* Standard security handler (PDF 1.7 table 3.19) */ @@ -270,13 +264,31 @@ pdf_free_crypt(pdf_crypt *crypt) */ static fz_error -pdf_parse_crypt_filter(pdf_crypt_filter *cf, fz_obj *dict, int defaultlength) +pdf_parse_crypt_filter(pdf_crypt_filter *cf, fz_obj *cf_obj, char *name, int defaultlength) { fz_obj *obj; + fz_obj *dict; + int is_identity = (strcmp(name, "Identity") == 0); + int is_stdcf = (!is_identity && (strcmp(name, "StdCF") == 0)); + if (!is_identity && !is_stdcf) + { + return fz_throw("Crypt Filter not Identity or StdCF (%d %d R)", fz_to_num(cf_obj), fz_to_gen(cf_obj)); + } cf->method = PDF_CRYPT_NONE; cf->length = defaultlength; + if (cf_obj == NULL) + { + cf->method = (is_identity ? PDF_CRYPT_NONE : PDF_CRYPT_RC4); + return fz_okay; + } + + dict = fz_dict_gets(cf_obj, name); + if (fz_is_dict(dict)) + { + return fz_throw("cannot parse crypt filter (%d %d R)", fz_to_num(cf_obj), fz_to_gen(cf_obj)); + } obj = fz_dict_gets(dict, "CFM"); if (fz_is_name(obj)) { @@ -805,15 +817,11 @@ pdf_open_crypt_with_filter(fz_stream *chain, pdf_crypt *crypt, char *name, int n if (strcmp(name, "Identity")) { - fz_obj *obj = fz_dict_gets(crypt->cf, name); - if (fz_is_dict(obj)) - { - error = pdf_parse_crypt_filter(&cf, obj, crypt->length); - if (error) - fz_catch(error, "cannot parse crypt filter (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); - else - return pdf_open_crypt_imp(chain, crypt, &cf, num, gen); - } + error = pdf_parse_crypt_filter(&cf, crypt->cf, name, crypt->length); + if (error) + fz_catch(error, "cannot parse crypt filter (%d %d R)", num, gen); + else + return pdf_open_crypt_imp(chain, crypt, &cf, num, gen); } return chain; } |