Merge branch 'STABLE-BRANCH-2-2'
[gnupg.git] / tools / mime-maker.c
1 /* mime-maker.c - Create MIME structures
2  * Copyright (C) 2016 g10 Code GmbH
3  * Copyright (C) 2016 Bundesamt für Sicherheit in der Informationstechnik
4  *
5  * This file is part of GnuPG.
6  *
7  * This file is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This file is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program; if not, see <https://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "../common/util.h"
27 #include "../common/zb32.h"
28 #include "mime-maker.h"
29
30
31 /* All valid characters in a header name.  */
32 #define HEADER_NAME_CHARS  ("abcdefghijklmnopqrstuvwxyz" \
33                             "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
34                             "-01234567890")
35
36 /* An object to store an header.  Also used for a list of headers.  */
37 struct header_s
38 {
39   struct header_s *next;
40   char *value;   /* Malloced value.  */
41   char name[1]; /* Name.  */
42 };
43 typedef struct header_s *header_t;
44
45
46 /* An object to store a MIME part.  A part is the header plus the
47  * content (body). */
48 struct part_s
49 {
50   struct part_s *next;  /* Next part in the current container.  */
51   struct part_s *child; /* Child container.  */
52   char *boundary;       /* Malloced boundary string.  */
53   header_t headers;     /* List of headers.  */
54   header_t *headers_tail;/* Address of last header in chain.  */
55   size_t bodylen;       /* Length of BODY.   */
56   char *body;           /* Malloced buffer with the body.  This is the
57                          * non-encoded value.  */
58   unsigned int partid;   /* The part ID.  */
59 };
60 typedef struct part_s *part_t;
61
62
63
64 /* Definition of the mime parser object.  */
65 struct mime_maker_context_s
66 {
67   void *cookie;                /* Cookie passed to all callbacks.  */
68
69   unsigned int verbose:1;      /* Enable verbose mode.  */
70   unsigned int debug:1;        /* Enable debug mode.  */
71
72   part_t mail;                 /* The MIME tree.  */
73   part_t current_part;
74
75   unsigned int partid_counter; /* Counter assign part ids.  */
76
77   int boundary_counter;  /* Used to create easy to read boundaries.  */
78   char *boundary_suffix; /* Random string used in the boundaries.  */
79
80   struct b64state *b64state;     /* NULL or malloced Base64 decoder state.  */
81
82   /* Helper to convey the output stream to recursive functions. */
83   estream_t outfp;
84 };
85
86
87 /* Create a new mime make object.  COOKIE is a values woich will be
88  * used as first argument for all callbacks registered with this
89  * object.  */
90 gpg_error_t
91 mime_maker_new (mime_maker_t *r_maker, void *cookie)
92 {
93   mime_maker_t ctx;
94
95   *r_maker = NULL;
96
97   ctx = xtrycalloc (1, sizeof *ctx);
98   if (!ctx)
99     return gpg_error_from_syserror ();
100   ctx->cookie = cookie;
101
102   *r_maker = ctx;
103   return 0;
104 }
105
106
107 static void
108 release_parts (part_t part)
109 {
110   while (part)
111     {
112       part_t partnext = part->next;
113       while (part->headers)
114         {
115           header_t hdrnext = part->headers->next;
116           xfree (part->headers);
117           part->headers = hdrnext;
118         }
119       release_parts (part->child);
120       xfree (part->boundary);
121       xfree (part->body);
122       xfree (part);
123       part = partnext;
124     }
125 }
126
127
128 /* Release a mime maker object.  */
129 void
130 mime_maker_release (mime_maker_t ctx)
131 {
132   if (!ctx)
133     return;
134
135   release_parts (ctx->mail);
136   xfree (ctx->boundary_suffix);
137   xfree (ctx);
138 }
139
140
141 /* Set verbose and debug mode.  */
142 void
143 mime_maker_set_verbose (mime_maker_t ctx, int level)
144 {
145   if (!level)
146     {
147       ctx->verbose = 0;
148       ctx->debug = 0;
149     }
150   else
151     {
152       ctx->verbose = 1;
153       if (level > 10)
154         ctx->debug = 1;
155     }
156 }
157
158
159 static void
160 dump_parts (part_t part, int level)
161 {
162   header_t hdr;
163
164   for (; part; part = part->next)
165     {
166       log_debug ("%*s[part %u]\n", level*2, "", part->partid);
167       for (hdr = part->headers; hdr; hdr = hdr->next)
168         {
169           log_debug ("%*s%s: %s\n", level*2, "", hdr->name, hdr->value);
170         }
171       if (part->body)
172         log_debug ("%*s[body %zu bytes]\n", level*2, "", part->bodylen);
173       if (part->child)
174         {
175           log_debug ("%*s[container]\n", level*2, "");
176           dump_parts (part->child, level+1);
177         }
178     }
179 }
180
181
182 /* Dump the mime tree for debugging.  */
183 void
184 mime_maker_dump_tree (mime_maker_t ctx)
185 {
186   dump_parts (ctx->mail, 0);
187 }
188
189
190 /* Find the parent node for NEEDLE starting at ROOT.  */
191 static part_t
192 find_parent (part_t root, part_t needle)
193 {
194   part_t node, n;
195
196   for (node = root->child; node; node = node->next)
197     {
198       if (node == needle)
199         return root;
200       if ((n = find_parent (node, needle)))
201         return n;
202     }
203   return NULL;
204 }
205
206 /* Find the part node from the PARTID.  */
207 static part_t
208 find_part (part_t root, unsigned int partid)
209 {
210   part_t node, n;
211
212   for (node = root->child; node; node = node->next)
213     {
214       if (node->partid == partid)
215         return root;
216       if ((n = find_part (node, partid)))
217         return n;
218     }
219   return NULL;
220 }
221
222
223 /* Create a boundary string.  Outr codes is aware of the general
224  * structure of that string (gebins with "=-=") so that
225  * it can protect against accidentally-used boundaries within the
226  * content.   */
227 static char *
228 generate_boundary (mime_maker_t ctx)
229 {
230   if (!ctx->boundary_suffix)
231     {
232       char buffer[12];
233
234       gcry_create_nonce (buffer, sizeof buffer);
235       ctx->boundary_suffix = zb32_encode (buffer, 8 * sizeof buffer);
236       if (!ctx->boundary_suffix)
237         return NULL;
238     }
239
240   ctx->boundary_counter++;
241   return es_bsprintf ("=-=%02d-%s=-=",
242                       ctx->boundary_counter, ctx->boundary_suffix);
243 }
244
245
246 /* Ensure that the context has a MAIL and CURRENT_PART object and
247  * return the parent object if available  */
248 static gpg_error_t
249 ensure_part (mime_maker_t ctx, part_t *r_parent)
250 {
251   if (!ctx->mail)
252     {
253       ctx->mail = xtrycalloc (1, sizeof *ctx->mail);
254       if (!ctx->mail)
255         {
256           if (r_parent)
257             *r_parent = NULL;
258           return gpg_error_from_syserror ();
259         }
260       log_assert (!ctx->current_part);
261       ctx->current_part = ctx->mail;
262       ctx->current_part->headers_tail = &ctx->current_part->headers;
263     }
264   log_assert (ctx->current_part);
265   if (r_parent)
266     *r_parent = find_parent (ctx->mail, ctx->current_part);
267
268   return 0;
269 }
270
271
272 /* Transform a header name into a standard capitalized format.
273  * "Content-Type".  Conversion stops at the colon. */
274 static void
275 capitalize_header_name (char *name)
276 {
277   unsigned char *p = name;
278   int first = 1;
279
280   /* Special cases first.  */
281   if (!ascii_strcasecmp (name, "MIME-Version"))
282     {
283       strcpy (name, "MIME-Version");
284       return;
285     }
286
287   /* Regular cases.  */
288   for (; *p && *p != ':'; p++)
289     {
290       if (*p == '-')
291         first = 1;
292       else if (first)
293         {
294           if (*p >= 'a' && *p <= 'z')
295             *p = *p - 'a' + 'A';
296           first = 0;
297         }
298       else if (*p >= 'A' && *p <= 'Z')
299         *p = *p - 'A' + 'a';
300     }
301 }
302
303
304 /* Check whether a header with NAME has already been set into PART.
305  * NAME must be in canonical capitalized format.  Return true or
306  * false. */
307 static int
308 have_header (part_t part, const char *name)
309 {
310   header_t hdr;
311
312   for (hdr = part->headers; hdr; hdr = hdr->next)
313     if (!strcmp (hdr->name, name))
314       return 1;
315   return 0;
316 }
317
318
319 /* Helper to add a header to a part.  */
320 static gpg_error_t
321 add_header (part_t part, const char *name, const char *value)
322 {
323   gpg_error_t err;
324   header_t hdr;
325   size_t namelen;
326   const char *s;
327   char *p;
328
329   if (!value)
330     {
331       s = strchr (name, '=');
332       if (!s)
333         return gpg_error (GPG_ERR_INV_ARG);
334       namelen = s - name;
335       value = s+1;
336     }
337   else
338     namelen = strlen (name);
339
340   hdr = xtrymalloc (sizeof *hdr + namelen);
341   if (!hdr)
342     return gpg_error_from_syserror ();
343   hdr->next = NULL;
344   memcpy (hdr->name, name, namelen);
345   hdr->name[namelen] = 0;
346
347   /* Check that the header name is valid.  We allow all lower and
348    * uppercase letters and, except for the first character, digits and
349    * the dash.  */
350   if (strspn (hdr->name, HEADER_NAME_CHARS) != namelen
351       || strchr ("-0123456789", *hdr->name))
352     {
353       xfree (hdr);
354       return gpg_error (GPG_ERR_INV_NAME);
355     }
356
357   capitalize_header_name (hdr->name);
358   hdr->value = xtrystrdup (value);
359   if (!hdr->value)
360     {
361       err = gpg_error_from_syserror ();
362       xfree (hdr);
363       return err;
364     }
365
366   for (p = hdr->value + strlen (hdr->value) - 1;
367        (p >= hdr->value
368         && (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r'));
369        p--)
370     *p = 0;
371   if (!(p >= hdr->value))
372     {
373       xfree (hdr->value);
374       xfree (hdr);
375       return gpg_error (GPG_ERR_INV_VALUE);  /* Only spaces.  */
376     }
377
378   if (part)
379     {
380       *part->headers_tail = hdr;
381       part->headers_tail = &hdr->next;
382     }
383   else
384     xfree (hdr);
385
386   return 0;
387 }
388
389
390 /* Add a header with NAME and VALUE to the current mail.  A LF in the
391  * VALUE will be handled automagically.  If NULL is used for VALUE it
392  * is expected that the NAME has the format "NAME=VALUE" and VALUE is
393  * taken from there.
394  *
395  * If no container has been added, the header will be used for the
396  * regular mail headers and not for a MIME part.  If the current part
397  * is in a container and a body has been added, we append a new part
398  * to the current container.  Thus for a non-MIME mail the caller
399  * needs to call this function followed by a call to add a body.  When
400  * adding a Content-Type the boundary parameter must not be included.
401  */
402 gpg_error_t
403 mime_maker_add_header (mime_maker_t ctx, const char *name, const char *value)
404 {
405   gpg_error_t err;
406   part_t part, parent;
407
408   /* Hack to use this function for a syntax check of NAME and VALUE.  */
409   if (!ctx)
410     return add_header (NULL, name, value);
411
412   err = ensure_part (ctx, &parent);
413   if (err)
414     return err;
415   part = ctx->current_part;
416
417   if ((part->body || part->child) && !parent)
418     {
419       /* We already have a body but no parent.  Adding another part is
420        * thus not possible.  */
421       return gpg_error (GPG_ERR_CONFLICT);
422     }
423   if (part->body || part->child)
424     {
425       /* We already have a body and there is a parent.  We now append
426        * a new part to the current container.  */
427       part = xtrycalloc (1, sizeof *part);
428       if (!part)
429         return gpg_error_from_syserror ();
430       part->partid = ++ctx->partid_counter;
431       part->headers_tail = &part->headers;
432       log_assert (!ctx->current_part->next);
433       ctx->current_part->next = part;
434       ctx->current_part = part;
435     }
436
437   /* If no NAME and no VALUE has been given we do not add a header.
438    * This can be used to create a new part without any header.  */
439   if (!name && !value)
440     return 0;
441
442   /* If we add Content-Type, make sure that we have a MIME-version
443    * header first; this simply looks better.  */
444   if (!ascii_strcasecmp (name, "Content-Type")
445       && !have_header (ctx->mail, "MIME-Version"))
446     {
447       err = add_header (ctx->mail, "MIME-Version", "1.0");
448       if (err)
449         return err;
450     }
451   return add_header (part, name, value);
452 }
453
454
455 /* Helper for mime_maker_add_{body,stream}.  */
456 static gpg_error_t
457 add_body (mime_maker_t ctx, const void *data, size_t datalen)
458 {
459   gpg_error_t err;
460   part_t part, parent;
461
462   err = ensure_part (ctx, &parent);
463   if (err)
464     return err;
465   part = ctx->current_part;
466   if (part->body)
467     return gpg_error (GPG_ERR_CONFLICT);
468
469   part->body = xtrymalloc (datalen? datalen : 1);
470   if (!part->body)
471     return gpg_error_from_syserror ();
472   part->bodylen = datalen;
473   if (data)
474     memcpy (part->body, data, datalen);
475
476   return 0;
477 }
478
479
480 /* Add STRING as body to the mail or the current MIME container.  A
481  * second call to this function or mime_make_add_body_data is not
482  * allowed.
483  *
484  * FIXME: We may want to have an append_body to add more data to a body.
485  */
486 gpg_error_t
487 mime_maker_add_body (mime_maker_t ctx, const char *string)
488 {
489   return add_body (ctx, string, strlen (string));
490 }
491
492
493 /* Add (DATA,DATALEN) as body to the mail or the current MIME
494  * container.  Note that a second call to this function or to
495  * mime_make_add_body is not allowed.  */
496 gpg_error_t
497 mime_maker_add_body_data (mime_maker_t ctx, const void *data, size_t datalen)
498 {
499   return add_body (ctx, data, datalen);
500 }
501
502
503 /* This is the same as mime_maker_add_body but takes a stream as
504  * argument.  As of now the stream is copied to the MIME object but
505  * eventually we may delay that and read the stream only at the time
506  * it is needed.  Note that the address of the stream object must be
507  * passed and that the ownership of the stream is transferred to this
508  * MIME object.  To indicate the latter the function will store NULL
509  * at the ADDR_STREAM so that a caller can't use that object anymore
510  * except for es_fclose which accepts a NULL pointer.  */
511 gpg_error_t
512 mime_maker_add_stream (mime_maker_t ctx, estream_t *stream_addr)
513 {
514   void *data;
515   size_t datalen;
516
517   es_rewind (*stream_addr);
518   if (es_fclose_snatch (*stream_addr, &data, &datalen))
519     return gpg_error_from_syserror ();
520   *stream_addr = NULL;
521   return add_body (ctx, data, datalen);
522 }
523
524
525 /* Add a new MIME container.  A container can be used instead of a
526  * body.  */
527 gpg_error_t
528 mime_maker_add_container (mime_maker_t ctx)
529 {
530   gpg_error_t err;
531   part_t part;
532
533   err = ensure_part (ctx, NULL);
534   if (err)
535     return err;
536   part = ctx->current_part;
537
538   if (part->body)
539     return gpg_error (GPG_ERR_CONFLICT); /* There is already a body. */
540   if (part->child || part->boundary)
541     return gpg_error (GPG_ERR_CONFLICT); /* There is already a container. */
542
543   /* Create a child node.  */
544   part->child = xtrycalloc (1, sizeof *part->child);
545   if (!part->child)
546     return gpg_error_from_syserror ();
547   part->child->headers_tail = &part->child->headers;
548
549   part->boundary = generate_boundary (ctx);
550   if (!part->boundary)
551     {
552       err = gpg_error_from_syserror ();
553       xfree (part->child);
554       part->child = NULL;
555       return err;
556     }
557
558   part = part->child;
559   part->partid = ++ctx->partid_counter;
560   ctx->current_part = part;
561
562   return 0;
563 }
564
565
566 /* Finish the current container.  */
567 gpg_error_t
568 mime_maker_end_container (mime_maker_t ctx)
569 {
570   gpg_error_t err;
571   part_t parent;
572
573   err = ensure_part (ctx, &parent);
574   if (err)
575     return err;
576   if (!parent)
577     return gpg_error (GPG_ERR_CONFLICT); /* No container.  */
578   while (parent->next)
579     parent = parent->next;
580   ctx->current_part = parent;
581   return 0;
582 }
583
584
585 /* Return the part-ID of the current part. */
586 unsigned int
587 mime_maker_get_partid (mime_maker_t ctx)
588 {
589   if (ensure_part (ctx, NULL))
590     return 0; /* Ooops.  */
591   return ctx->current_part->partid;
592 }
593
594
595 /* Write a header and handle emdedded LFs.  If BOUNDARY is not NULL it
596  * is appended to the value.  */
597 /* Fixme: Add automatic line wrapping.  */
598 static gpg_error_t
599 write_header (mime_maker_t ctx, const char *name, const char *value,
600               const char *boundary)
601 {
602   const char *s;
603
604   es_fprintf (ctx->outfp, "%s: ", name);
605
606   /* Note that add_header made sure that VALUE does not end with a LF.
607    * Thus we can assume that a LF is followed by non-whitespace.  */
608   for (s = value; *s; s++)
609     {
610       if (*s == '\n')
611         es_fputs ("\r\n\t", ctx->outfp);
612       else
613         es_fputc (*s, ctx->outfp);
614     }
615   if (boundary)
616     {
617       if (s > value && s[-1] != ';')
618         es_fputc (';', ctx->outfp);
619       es_fprintf (ctx->outfp, "\r\n\tboundary=\"%s\"", boundary);
620     }
621
622   es_fputs ("\r\n", ctx->outfp);
623
624   return es_ferror (ctx->outfp)? gpg_error_from_syserror () : 0;
625 }
626
627
628 static gpg_error_t
629 write_gap (mime_maker_t ctx)
630 {
631   es_fputs ("\r\n", ctx->outfp);
632   return es_ferror (ctx->outfp)? gpg_error_from_syserror () : 0;
633 }
634
635
636 static gpg_error_t
637 write_boundary (mime_maker_t ctx, const char *boundary, int last)
638 {
639   es_fprintf (ctx->outfp, "\r\n--%s%s\r\n", boundary, last?"--":"");
640   return es_ferror (ctx->outfp)? gpg_error_from_syserror () : 0;
641 }
642
643
644 /* Fixme: Apply required encoding.  */
645 static gpg_error_t
646 write_body (mime_maker_t ctx, const void *body, size_t bodylen)
647 {
648   const char *s;
649
650   for (s = body; bodylen; s++, bodylen--)
651     {
652       if (*s == '\n' && !(s > (const char *)body && s[-1] == '\r'))
653         es_fputc ('\r', ctx->outfp);
654       es_fputc (*s, ctx->outfp);
655     }
656
657   return es_ferror (ctx->outfp)? gpg_error_from_syserror () : 0;
658 }
659
660
661 /* Recursive worker for mime_maker_make.  */
662 static gpg_error_t
663 write_tree (mime_maker_t ctx, part_t parent, part_t part)
664 {
665   gpg_error_t err;
666   header_t hdr;
667
668   for (; part; part = part->next)
669     {
670       for (hdr = part->headers; hdr; hdr = hdr->next)
671         {
672           if (part->child && !strcmp (hdr->name, "Content-Type"))
673             err = write_header (ctx, hdr->name, hdr->value, part->boundary);
674           else
675             err = write_header (ctx, hdr->name, hdr->value, NULL);
676           if (err)
677             return err;
678         }
679       err = write_gap (ctx);
680       if (err)
681         return err;
682       if (part->body)
683         {
684           err = write_body (ctx, part->body, part->bodylen);
685           if (err)
686             return err;
687         }
688       if (part->child)
689         {
690           log_assert (part->boundary);
691           err = write_boundary (ctx, part->boundary, 0);
692           if (!err)
693             err = write_tree (ctx, part, part->child);
694           if (!err)
695             err = write_boundary (ctx, part->boundary, 1);
696           if (err)
697             return err;
698         }
699
700       if (part->next)
701         {
702           log_assert (parent && parent->boundary);
703           err = write_boundary (ctx, parent->boundary, 0);
704           if (err)
705             return err;
706         }
707     }
708   return 0;
709 }
710
711
712 /* Add headers we always require.  */
713 static gpg_error_t
714 add_missing_headers (mime_maker_t ctx)
715 {
716   gpg_error_t err;
717
718   if (!ctx->mail)
719     return gpg_error (GPG_ERR_NO_DATA);
720   if (!have_header (ctx->mail, "MIME-Version"))
721     {
722       /* Even if a Content-Type has never been set, we want to
723        * announce that we do MIME.  */
724       err = add_header (ctx->mail, "MIME-Version", "1.0");
725       if (err)
726         goto leave;
727     }
728
729   if (!have_header (ctx->mail, "Date"))
730     {
731       char *p = rfctimestamp (make_timestamp ());
732       if (!p)
733         err = gpg_error_from_syserror ();
734       else
735         err = add_header (ctx->mail, "Date", p);
736       xfree (p);
737       if (err)
738         goto leave;
739     }
740
741   err = 0;
742
743  leave:
744   return err;
745 }
746
747
748 /* Create message from the tree MIME and write it to FP.  Note that
749  * the output uses only a LF and a later called sendmail(1) is
750  * expected to convert them to network line endings.  */
751 gpg_error_t
752 mime_maker_make (mime_maker_t ctx, estream_t fp)
753 {
754   gpg_error_t err;
755
756   err = add_missing_headers (ctx);
757   if (err)
758     return err;
759
760   ctx->outfp = fp;
761   err = write_tree (ctx, NULL, ctx->mail);
762
763   ctx->outfp = NULL;
764   return err;
765 }
766
767
768 /* Create a stream object from the MIME part identified by PARTID and
769  * store it at R_STREAM.  If PARTID identifies a container the entire
770  * tree is returned. Using that function may read stream objects
771  * which have been added as MIME bodies.  The caller must close the
772  * stream object. */
773 gpg_error_t
774 mime_maker_get_part (mime_maker_t ctx, unsigned int partid, estream_t *r_stream)
775 {
776   gpg_error_t err;
777   part_t part;
778   estream_t fp;
779
780   *r_stream = NULL;
781
782   /* When the entire tree is requested, we make sure that all missing
783    * headers are applied.  We don't do that if only a part is
784    * requested because the additional headers (like Date:) will only
785    * be added to part 0 headers anyway. */
786   if (!partid)
787     {
788        err = add_missing_headers (ctx);
789        if (err)
790          return err;
791        part = ctx->mail;
792     }
793   else
794     part = find_part (ctx->mail, partid);
795
796   /* For now we use a memory stream object; however it would also be
797    * possible to create an object created on the fly while the caller
798    * is reading the returned stream.  */
799   fp = es_fopenmem (0, "w+b");
800   if (!fp)
801     return gpg_error_from_syserror ();
802
803   ctx->outfp = fp;
804   err = write_tree (ctx, NULL, part);
805   ctx->outfp = NULL;
806
807   if (!err)
808     {
809       es_rewind (fp);
810       *r_stream = fp;
811     }
812   else
813     es_fclose (fp);
814
815   return err;
816 }