pdfsign.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. // Copyright (C) 2004-2021 Artifex Software, Inc.
  2. //
  3. // This file is part of MuPDF.
  4. //
  5. // MuPDF is free software: you can redistribute it and/or modify it under the
  6. // terms of the GNU Affero General Public License as published by the Free
  7. // Software Foundation, either version 3 of the License, or (at your option)
  8. // any later version.
  9. //
  10. // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
  11. // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  12. // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  13. // details.
  14. //
  15. // You should have received a copy of the GNU Affero General Public License
  16. // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
  17. //
  18. // Alternative licensing terms are available from the licensor.
  19. // For commercial licensing, see <https://www.artifex.com/> or contact
  20. // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  21. // CA 94129, USA, for further information.
  22. /*
  23. * PDF signature tool: verify and sign digital signatures in PDF files.
  24. */
  25. #include "mupdf/fitz.h"
  26. #include "mupdf/pdf.h"
  27. #include "mupdf/helpers/pkcs7-openssl.h"
  28. #include <string.h>
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. static char *infile = NULL;
  32. static char *outfile = NULL;
  33. static char *certificatefile = NULL;
  34. static char *certificatepassword = "";
  35. static int verify = 0;
  36. static int clear = 0;
  37. static int sign = 0;
  38. static int list = 1;
  39. static int usage(void)
  40. {
  41. fprintf(stderr,
  42. "usage: mutool sign [options] input.pdf [signature object numbers]\n"
  43. "\t-p -\tpassword\n"
  44. "\t-v \tverify signature\n"
  45. "\t-c \tclear signatures\n"
  46. "\t-s -\tsign signatures using certificate file\n"
  47. "\t-P -\tcertificate password\n"
  48. "\t-o -\toutput file name\n"
  49. );
  50. return 1;
  51. }
  52. static void verify_signature(fz_context *ctx, pdf_document *doc, pdf_obj *signature)
  53. {
  54. char *name;
  55. pdf_signature_error err;
  56. pdf_pkcs7_verifier *verifier;
  57. int edits;
  58. pdf_pkcs7_distinguished_name *dn = NULL;
  59. printf("Verifying signature %d:\n", pdf_to_num(ctx, signature));
  60. if (!pdf_signature_is_signed(ctx, doc, signature))
  61. {
  62. printf("\tSignature is not signed.\n");
  63. return;
  64. }
  65. verifier = pkcs7_openssl_new_verifier(ctx);
  66. fz_var(dn);
  67. fz_try(ctx)
  68. {
  69. dn = pdf_signature_get_signatory(ctx, verifier, doc, signature);
  70. if (dn)
  71. {
  72. name = pdf_signature_format_distinguished_name(ctx, dn);
  73. printf("\tDistinguished name: %s\n", name);
  74. fz_free(ctx, name);
  75. }
  76. else
  77. {
  78. printf("\tSignature information missing.\n");
  79. }
  80. err = pdf_check_certificate(ctx, verifier, doc, signature);
  81. if (err)
  82. printf("\tCertificate error: %s\n", pdf_signature_error_description(err));
  83. else
  84. printf("\tCertificate is trusted.\n");
  85. err = pdf_check_digest(ctx, verifier, doc, signature);
  86. edits = pdf_signature_incremental_change_since_signing(ctx, doc, signature);
  87. if (err)
  88. printf("\tDigest error: %s\n", pdf_signature_error_description(err));
  89. else if (edits)
  90. printf("\tThe signature is valid but there have been edits since signing.\n");
  91. else
  92. printf("\tThe document is unchanged since signing.\n");
  93. }
  94. fz_always(ctx)
  95. {
  96. pdf_signature_drop_distinguished_name(ctx, dn);
  97. pdf_drop_verifier(ctx, verifier);
  98. }
  99. fz_catch(ctx)
  100. {
  101. fz_rethrow(ctx);
  102. }
  103. }
  104. static void clear_signature(fz_context *ctx, pdf_document *doc, pdf_obj *signature)
  105. {
  106. pdf_page *page = NULL;
  107. pdf_annot *widget;
  108. pdf_obj *parent;
  109. int pageno, pagenoend;
  110. fz_var(page);
  111. printf("Clearing signature %d.\n", pdf_to_num(ctx, signature));
  112. fz_try(ctx)
  113. {
  114. parent = pdf_dict_get(ctx, signature, PDF_NAME(P));
  115. if (pdf_is_dict(ctx, parent))
  116. {
  117. pageno = pdf_lookup_page_number(ctx, doc, parent);
  118. pagenoend = pageno+1;
  119. }
  120. else
  121. {
  122. pageno = 0;
  123. pagenoend = pdf_count_pages(ctx, doc);
  124. }
  125. for (; pageno < pagenoend; pageno++)
  126. {
  127. page = pdf_load_page(ctx, doc, pageno);
  128. for (widget = pdf_first_widget(ctx, page); widget; widget = pdf_next_widget(ctx, widget))
  129. if (pdf_widget_type(ctx, widget) == PDF_WIDGET_TYPE_SIGNATURE && !pdf_objcmp_resolve(ctx, pdf_annot_obj(ctx, widget), signature))
  130. pdf_clear_signature(ctx, widget);
  131. fz_drop_page(ctx, (fz_page *) page);
  132. page = NULL;
  133. }
  134. }
  135. fz_always(ctx)
  136. fz_drop_page(ctx, (fz_page*)page);
  137. fz_catch(ctx)
  138. fz_rethrow(ctx);
  139. }
  140. static void sign_signature(fz_context *ctx, pdf_document *doc, pdf_obj *signature)
  141. {
  142. pdf_pkcs7_signer *signer = NULL;
  143. pdf_page *page = NULL;
  144. pdf_annot *widget;
  145. pdf_obj *parent;
  146. int pageno, pagenoend;
  147. fz_var(page);
  148. fz_var(signer);
  149. printf("Signing signature %d.\n", pdf_to_num(ctx, signature));
  150. fz_try(ctx)
  151. {
  152. signer = pkcs7_openssl_read_pfx(ctx, certificatefile, certificatepassword);
  153. parent = pdf_dict_get(ctx, signature, PDF_NAME(P));
  154. if (pdf_is_dict(ctx, parent))
  155. {
  156. pageno = pdf_lookup_page_number(ctx, doc, parent);
  157. pagenoend = pageno+1;
  158. }
  159. else
  160. {
  161. pageno = 0;
  162. pagenoend = pdf_count_pages(ctx, doc);
  163. }
  164. for (; pageno < pagenoend; pageno++)
  165. {
  166. page = pdf_load_page(ctx, doc, pageno);
  167. for (widget = pdf_first_widget(ctx, page); widget; widget = pdf_next_widget(ctx, widget))
  168. if (pdf_widget_type(ctx, widget) == PDF_WIDGET_TYPE_SIGNATURE && !pdf_objcmp_resolve(ctx, pdf_annot_obj(ctx, widget), signature))
  169. pdf_sign_signature(ctx, widget, signer,
  170. PDF_SIGNATURE_DEFAULT_APPEARANCE,
  171. NULL,
  172. NULL,
  173. NULL);
  174. fz_drop_page(ctx, (fz_page *) page);
  175. page = NULL;
  176. }
  177. }
  178. fz_always(ctx)
  179. {
  180. fz_drop_page(ctx, (fz_page*)page);
  181. pdf_drop_signer(ctx, signer);
  182. }
  183. fz_catch(ctx)
  184. fz_rethrow(ctx);
  185. }
  186. static void list_signature(fz_context *ctx, pdf_document *doc, pdf_obj *signature)
  187. {
  188. pdf_pkcs7_distinguished_name *dn;
  189. pdf_pkcs7_verifier *verifier;
  190. if (!pdf_signature_is_signed(ctx, doc, signature))
  191. {
  192. printf("%5d: Signature is not signed.\n", pdf_to_num(ctx, signature));
  193. return;
  194. }
  195. verifier = pkcs7_openssl_new_verifier(ctx);
  196. dn = pdf_signature_get_signatory(ctx, verifier, doc, signature);
  197. if (dn)
  198. {
  199. char *s = pdf_signature_format_distinguished_name(ctx, dn);
  200. printf("%5d: Distinguished name: %s\n", pdf_to_num(ctx, signature), s);
  201. fz_free(ctx, s);
  202. pdf_signature_drop_distinguished_name(ctx, dn);
  203. }
  204. else
  205. {
  206. printf("%5d: Signature information missing.\n", pdf_to_num(ctx, signature));
  207. }
  208. pdf_drop_verifier(ctx, verifier);
  209. }
  210. static void process_field(fz_context *ctx, pdf_document *doc, pdf_obj *field)
  211. {
  212. if (pdf_dict_get_inheritable(ctx, field, PDF_NAME(FT)) != PDF_NAME(Sig))
  213. fz_warn(ctx, "%d is not a signature, skipping", pdf_to_num(ctx, field));
  214. else
  215. {
  216. if (list)
  217. list_signature(ctx, doc, field);
  218. if (verify)
  219. verify_signature(ctx, doc, field);
  220. if (clear)
  221. clear_signature(ctx, doc, field);
  222. if (sign)
  223. sign_signature(ctx, doc, field);
  224. }
  225. }
  226. static int process_field_hierarchy(fz_context *ctx, pdf_document *doc, pdf_obj *field, pdf_cycle_list *cycle_up)
  227. {
  228. pdf_cycle_list cycle;
  229. pdf_obj *kids;
  230. int x = 0;
  231. if (field == NULL || pdf_cycle(ctx, &cycle, cycle_up, field))
  232. fz_throw(ctx, FZ_ERROR_SYNTAX, "recursive field hierarchy");
  233. kids = pdf_dict_get(ctx, field, PDF_NAME(Kids));
  234. if (kids)
  235. {
  236. int i, n;
  237. n = pdf_array_len(ctx, kids);
  238. for (i = 0; i < n; ++i)
  239. {
  240. pdf_obj *kid = pdf_array_get(ctx, kids, i);
  241. x += process_field_hierarchy(ctx, doc, kid, &cycle);
  242. }
  243. }
  244. else if (pdf_dict_get_inheritable(ctx, field, PDF_NAME(FT)) == PDF_NAME(Sig))
  245. {
  246. process_field(ctx, doc, field);
  247. ++x;
  248. }
  249. return x;
  250. }
  251. static int process_acro_form(fz_context *ctx, pdf_document *doc)
  252. {
  253. pdf_obj *trailer = pdf_trailer(ctx, doc);
  254. pdf_obj *root = pdf_dict_get(ctx, trailer, PDF_NAME(Root));
  255. pdf_obj *acroform = pdf_dict_get(ctx, root, PDF_NAME(AcroForm));
  256. pdf_obj *fields = pdf_dict_get(ctx, acroform, PDF_NAME(Fields));
  257. int i, x, n = pdf_array_len(ctx, fields);
  258. for (i = x = 0; i < n; ++i)
  259. x += process_field_hierarchy(ctx, doc, pdf_array_get(ctx, fields, i), NULL);
  260. return x;
  261. }
  262. int pdfsign_main(int argc, char **argv)
  263. {
  264. fz_context *ctx;
  265. pdf_document *doc = NULL;
  266. char *password = "";
  267. int c;
  268. while ((c = fz_getopt(argc, argv, "co:p:s:vP:")) != -1)
  269. {
  270. switch (c)
  271. {
  272. case 'c': list = 0; clear = 1; break;
  273. case 'o': outfile = fz_optarg; break;
  274. case 'p': password = fz_optarg; break;
  275. case 'P': certificatepassword = fz_optarg; break;
  276. case 's': list = 0; sign = 1; certificatefile = fz_optarg; break;
  277. case 'v': list = 0; verify = 1; break;
  278. default: return usage();
  279. }
  280. }
  281. if (argc - fz_optind < 1)
  282. return usage();
  283. infile = argv[fz_optind++];
  284. if (!clear && !sign && !verify && argc - fz_optind > 0)
  285. {
  286. list = 0;
  287. verify = 1;
  288. }
  289. ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
  290. if (!ctx)
  291. {
  292. fprintf(stderr, "cannot initialize context\n");
  293. exit(1);
  294. }
  295. fz_var(doc);
  296. fz_try(ctx)
  297. {
  298. doc = pdf_open_document(ctx, infile);
  299. if (pdf_needs_password(ctx, doc))
  300. if (!pdf_authenticate_password(ctx, doc, password))
  301. fz_warn(ctx, "cannot authenticate password: %s", infile);
  302. if (argc - fz_optind <= 0 || list)
  303. {
  304. if (!process_acro_form(ctx, doc))
  305. {
  306. fprintf(stderr, "No signatures found!\n");
  307. exit(1);
  308. }
  309. }
  310. else
  311. {
  312. while (argc - fz_optind)
  313. {
  314. pdf_obj *field = pdf_new_indirect(ctx, doc, fz_atoi(argv[fz_optind]), 0);
  315. process_field(ctx, doc, field);
  316. pdf_drop_obj(ctx, field);
  317. fz_optind++;
  318. }
  319. }
  320. if (clear || sign)
  321. {
  322. pdf_write_options opts = pdf_default_write_options;
  323. opts.do_incremental = 1;
  324. if (!outfile)
  325. outfile = "out.pdf";
  326. pdf_save_document(ctx, doc, outfile, &opts);
  327. }
  328. }
  329. fz_always(ctx)
  330. pdf_drop_document(ctx, doc);
  331. fz_catch(ctx)
  332. {
  333. fz_report_error(ctx);
  334. fz_log_error(ctx, "error processing signatures");
  335. }
  336. fz_flush_warnings(ctx);
  337. fz_drop_context(ctx);
  338. return 0;
  339. }