Poems for AllowSetForegroundWindow (W32)
[gnupg.git] / sm / base64.c
1 /* base64.c 
2  *      Copyright (C) 2001, 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h> 
26 #include <time.h>
27 #include <assert.h>
28
29 #include "gpgsm.h"
30
31
32 #include <ksba.h>
33
34 #include "i18n.h"
35
36 #ifdef HAVE_DOSISH_SYSTEM
37   #define LF "\r\n"
38 #else
39   #define LF "\n"
40 #endif
41
42 /* data used by the reader callbacks */
43 struct reader_cb_parm_s {
44   FILE *fp;
45   
46   unsigned char line[1024];
47   int linelen;
48   int readpos;
49   int have_lf;
50   unsigned long line_counter;
51
52   int allow_multi_pem;  /* Allow processing of multiple PEM objects. */
53   int autodetect;       /* Try to detect the input encoding. */
54   int assume_pem;       /* Assume input encoding is PEM. */
55   int assume_base64;    /* Assume input is base64 encoded. */
56
57   int identified;
58   int is_pem;
59   int is_base64;
60   int stop_seen;
61   int might_be_smime;
62
63   int eof_seen;         
64
65   struct {
66     int idx;
67     unsigned char val;
68     int stop_seen;
69   } base64;
70 };
71
72 /* data used by the writer callbacks */
73 struct writer_cb_parm_s {
74   FILE *fp;            /* FP is only used if STREAM is NULL.  */
75   estream_t stream;    /* Alternative output if not NULL.  */
76
77   const char *pem_name;
78   
79   int wrote_begin;
80   int did_finish;
81
82   struct {
83     int idx;
84     int quad_count;
85     unsigned char radbuf[4];
86   } base64;
87
88 };
89
90
91 /* context for this module's functions */
92 struct base64_context_s {
93   union {
94     struct reader_cb_parm_s rparm;
95     struct writer_cb_parm_s wparm;
96   } u;
97
98   union {
99     ksba_reader_t reader;
100     ksba_writer_t writer;
101   } u2;
102 };
103
104
105 /* The base-64 character list */
106 static char bintoasc[64] = 
107        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 
108        "abcdefghijklmnopqrstuvwxyz" 
109        "0123456789+/"; 
110 /* The reverse base-64 list */
111 static unsigned char asctobin[256] = {
112   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
113   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
114   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
115   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, 
116   0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 
117   0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 
118   0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 
119   0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 
120   0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 
121   0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 
122   0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
123   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
124   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
125   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
126   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
127   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
128   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
129   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
130   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
131   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
132   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
133   0xff, 0xff, 0xff, 0xff
134 };
135
136
137 static int
138 has_only_base64 (const unsigned char *line, int linelen)
139 {
140   if (linelen < 20)
141     return 0;
142   for (; linelen; line++, linelen--)
143     {
144       if (*line == '\n' || (linelen > 1 && *line == '\r' && line[1] == '\n'))
145           break;
146       if ( !strchr (bintoasc, *line) )
147         return 0;
148     }
149   return 1;  /* yes */
150 }
151
152 static int
153 is_empty_line (const unsigned char *line, int linelen)
154 {
155   if (linelen >= 2 && *line == '\r' && line[1] == '\n')
156     return 1;
157   if (linelen >= 1 && *line == '\n')
158     return 1;
159   return 0;
160 }
161
162
163 static int
164 base64_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
165 {
166   struct reader_cb_parm_s *parm = cb_value;
167   size_t n;
168   int c, c2;
169
170   *nread = 0;
171   if (!buffer)
172     return -1; /* not supported */
173
174  next:
175   if (!parm->linelen)
176     {
177       /* read an entire line or up to the size of the buffer */
178       parm->line_counter++;
179       parm->have_lf = 0;
180       for (n=0; n < DIM(parm->line);)
181         {
182           c = getc (parm->fp);
183           if (c == EOF)
184             {
185               parm->eof_seen = 1;
186               if (ferror (parm->fp))
187                 return -1;
188               break; 
189             }
190           parm->line[n++] = c;
191           if (c == '\n')
192             {
193               parm->have_lf = 1;
194               /* Fixme: we need to skip overlong lines while detecting
195                  the dashed lines */
196               break;
197             }
198         }
199       parm->linelen = n;
200       if (!n)
201         return -1; /* eof */
202       parm->readpos = 0;
203     }
204
205   if (!parm->identified)
206     {
207       if (!parm->autodetect)
208         {
209           if (parm->assume_pem)
210             {
211               /* wait for the header line */
212               parm->linelen = parm->readpos = 0;
213               if (!parm->have_lf 
214                   || strncmp ((char*)parm->line, "-----BEGIN ", 11)
215                   || !strncmp ((char*)parm->line+11, "PGP ", 4))
216                 goto next;
217               parm->is_pem = 1;
218             }
219           else if (parm->assume_base64)
220             parm->is_base64 = 1;
221         }
222       else if (parm->line_counter == 1 && !parm->have_lf)
223         {
224           /* first line too long - assume DER encoding */
225           parm->is_pem = 0;
226         }
227       else if (parm->line_counter == 1 && parm->linelen && *parm->line == 0x30)
228         {
229           /* the very first byte does pretty much look like a SEQUENCE tag*/
230           parm->is_pem = 0;
231         }
232       else if ( parm->have_lf
233                 && !strncmp ((char*)parm->line, "-----BEGIN ", 11)
234                 && strncmp ((char *)parm->line+11, "PGP ", 4) )
235         {
236           /* Fixme: we must only compare if the line really starts at
237              the beginning */
238           parm->is_pem = 1;
239           parm->linelen = parm->readpos = 0;
240         }
241       else if ( parm->have_lf && parm->line_counter == 1
242                 && parm->linelen >= 13
243                 && !ascii_memcasecmp (parm->line, "Content-Type:", 13))
244         { /* might be a S/MIME body */
245           parm->might_be_smime = 1;
246           parm->linelen = parm->readpos = 0;
247           goto next;
248         }
249       else if (parm->might_be_smime == 1
250                && is_empty_line (parm->line, parm->linelen))
251         {
252           parm->might_be_smime = 2;
253           parm->linelen = parm->readpos = 0;
254           goto next;
255         }
256       else if (parm->might_be_smime == 2)
257         {
258           parm->might_be_smime = 0;
259           if ( !has_only_base64 (parm->line, parm->linelen))
260             {
261               parm->linelen = parm->readpos = 0;
262               goto next;
263             }
264           parm->is_pem = 1;
265         }
266       else
267         {
268           parm->linelen = parm->readpos = 0;
269           goto next;
270         }
271       parm->identified = 1;
272       parm->base64.stop_seen = 0;
273       parm->base64.idx = 0;
274     }
275   
276
277   n = 0;
278   if (parm->is_pem || parm->is_base64)
279     {  
280       if (parm->is_pem && parm->have_lf
281           && !strncmp ((char*)parm->line, "-----END ", 9))
282         { 
283           parm->identified = 0;
284           parm->linelen = parm->readpos = 0;
285
286           /* If the caller want to read multiple PEM objects from one
287              file, we have to reset our internal state and return a
288              EOF immediately. The caller is the expected to use
289              ksba_reader_clear to clear the EOF condition and continue
290              to read.  If we don't want to do that we just return 0
291              bytes which will force the ksba_reader to skip until
292              EOF. */
293           if (parm->allow_multi_pem)
294             {
295               parm->identified = 0;
296               parm->autodetect = 0;
297               parm->assume_pem = 1;
298               parm->stop_seen = 0;
299               return -1; /* Send EOF now. */
300             }
301         }
302       else if (parm->stop_seen)
303         { /* skip the rest of the line */
304           parm->linelen = parm->readpos = 0;
305         }
306       else
307         {
308           int idx = parm->base64.idx;
309           unsigned char val = parm->base64.val;
310
311           while (n < count && parm->readpos < parm->linelen )
312             {
313               c = parm->line[parm->readpos++];
314               if (c == '\n' || c == ' ' || c == '\r' || c == '\t')
315                 continue;
316               if (c == '=')
317                 { /* pad character: stop */
318                   if (idx == 1)
319                     buffer[n++] = val; 
320                   parm->stop_seen = 1;
321                   break;
322                 }
323               if( (c = asctobin[(c2=c)]) == 255 ) 
324                 {
325                   log_error (_("invalid radix64 character %02x skipped\n"),
326                              c2);
327                   continue;
328                 }
329               switch (idx) 
330                 {
331                 case 0: 
332                   val = c << 2;
333                   break;
334                 case 1: 
335                   val |= (c>>4)&3;
336                   buffer[n++] = val;
337                   val = (c<<4)&0xf0;
338                   break;
339                 case 2: 
340                   val |= (c>>2)&15;
341                   buffer[n++] = val;
342                   val = (c<<6)&0xc0;
343                   break;
344                 case 3: 
345                   val |= c&0x3f;
346                   buffer[n++] = val;
347                   break;
348                 }
349               idx = (idx+1) % 4;
350             }
351           if (parm->readpos == parm->linelen)
352             parm->linelen = parm->readpos = 0;
353
354           parm->base64.idx = idx;
355           parm->base64.val = val;
356         }
357     }
358   else
359     { /* DER encoded */
360       while (n < count && parm->readpos < parm->linelen)
361           buffer[n++] = parm->line[parm->readpos++];
362       if (parm->readpos == parm->linelen)
363         parm->linelen = parm->readpos = 0;
364     }
365
366   *nread = n;
367   return 0;
368 }
369
370
371
372 static int
373 simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
374 {
375   struct reader_cb_parm_s *parm = cb_value;
376   size_t n;
377   int c = 0;
378
379   *nread = 0;
380   if (!buffer)
381     return -1; /* not supported */
382
383   for (n=0; n < count; n++)
384     {
385       c = getc (parm->fp);
386       if (c == EOF)
387         {
388           parm->eof_seen = 1;
389           if ( ferror (parm->fp) )
390             return -1;
391           if (n)
392             break; /* return what we have before an EOF */
393           return -1;
394         }
395       *(byte *)buffer++ = c;
396     }
397
398   *nread = n;
399   return 0;
400 }
401
402
403
404 \f
405 /* Call either es_putc or the plain putc.  */
406 static void
407 do_putc (int value, FILE *fp, estream_t stream)
408 {
409   if (stream)
410     es_putc (value, stream);
411   else
412     putc (value, fp);
413 }
414
415 /* Call either es_fputs or the plain fputs.  */
416 static void
417 do_fputs (const char *string, FILE *fp, estream_t stream)
418 {
419   if (stream)
420     es_fputs (string, stream);
421   else
422     fputs (string, fp);
423 }
424
425
426 static int
427 base64_writer_cb (void *cb_value, const void *buffer, size_t count)
428 {
429   struct writer_cb_parm_s *parm = cb_value;
430   unsigned char radbuf[4];
431   int i, c, idx, quad_count;
432   const unsigned char *p;
433   FILE *fp = parm->fp;
434   estream_t stream = parm->stream;
435
436   if (!count)
437     return 0;
438
439   if (!parm->wrote_begin)
440     {
441       if (parm->pem_name)
442         {
443           do_fputs ("-----BEGIN ", fp, stream);
444           do_fputs (parm->pem_name, fp, stream);
445           do_fputs ("-----\n", fp, stream);
446         }
447       parm->wrote_begin = 1;
448       parm->base64.idx = 0;
449       parm->base64.quad_count = 0;
450     }
451
452   idx = parm->base64.idx;
453   quad_count = parm->base64.quad_count;
454   for (i=0; i < idx; i++)
455     radbuf[i] = parm->base64.radbuf[i];
456
457   for (p=buffer; count; p++, count--)
458     {
459       radbuf[idx++] = *p;
460       if (idx > 2)
461         {
462           idx = 0;
463           c = bintoasc[(*radbuf >> 2) & 077];
464           do_putc (c, fp, stream);
465           c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
466           do_putc (c, fp, stream);
467           c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
468           do_putc (c, fp, stream);
469           c = bintoasc[radbuf[2]&077];
470           do_putc (c, fp, stream);
471           if (++quad_count >= (64/4)) 
472             {
473               do_fputs (LF, fp, stream);
474               quad_count = 0;
475             }
476         }
477     }
478   for (i=0; i < idx; i++)
479     parm->base64.radbuf[i] = radbuf[i];
480   parm->base64.idx = idx;
481   parm->base64.quad_count = quad_count;
482
483   return ((stream? es_ferror (stream) : ferror (fp)) 
484           ? gpg_error_from_syserror () 
485           : 0);
486 }
487
488 /* This callback is only used in stream mode.  Hiowever, we don't
489    restrict it to this.  */
490 static int
491 plain_writer_cb (void *cb_value, const void *buffer, size_t count)
492 {
493   struct writer_cb_parm_s *parm = cb_value;
494   FILE *fp = parm->fp;
495   estream_t stream = parm->stream;
496
497   if (!count)
498     return 0;
499
500   if (stream)
501     es_write (stream, buffer, count, NULL);
502   else
503     fwrite (buffer, count, 1, fp);
504
505   return ((stream? es_ferror (stream) : ferror (fp)) 
506           ? gpg_error_from_syserror () 
507           : 0);
508 }
509
510 static int
511 base64_finish_write (struct writer_cb_parm_s *parm)
512 {
513   unsigned char radbuf[4];
514   int i, c, idx, quad_count;
515   FILE *fp = parm->fp;
516   estream_t stream = parm->stream;
517
518   if (!parm->wrote_begin)
519     return 0; /* Nothing written or we are not called in base-64 mode. */
520
521   /* flush the base64 encoding */
522   idx = parm->base64.idx;
523   quad_count = parm->base64.quad_count;
524   for (i=0; i < idx; i++)
525     radbuf[i] = parm->base64.radbuf[i];
526
527   if (idx)
528     {
529       c = bintoasc[(*radbuf>>2)&077];
530       do_putc (c, fp, stream);
531       if (idx == 1)
532         {
533           c = bintoasc[((*radbuf << 4) & 060) & 077];
534           do_putc (c, fp, stream);
535           do_putc ('=', fp, stream);
536           do_putc ('=', fp, stream);
537         }
538       else 
539         { 
540           c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
541           do_putc (c, fp, stream);
542           c = bintoasc[((radbuf[1] << 2) & 074) & 077];
543           do_putc (c, fp, stream);
544           do_putc ('=', fp, stream);
545
546         }
547       if (++quad_count >= (64/4)) 
548         {
549           do_fputs (LF, fp, stream);
550           quad_count = 0;
551         }
552     }
553
554   if (quad_count)
555     do_fputs (LF, fp, stream);
556
557   if (parm->pem_name)
558     {
559       do_fputs ("-----END ", fp, stream);
560       do_fputs (parm->pem_name, fp, stream);
561       do_fputs ("-----\n", fp, stream);
562     }
563
564   return ((stream? es_ferror (stream) : ferror (fp)) 
565           ? gpg_error_from_syserror () 
566           : 0);
567 }
568
569
570
571 \f
572 /* Create a reader for the given file descriptor.  Depending on the
573    control information an input decoding is automagically choosen.
574    The function returns a Base64Context object which must be passed to
575    the gpgme_destroy_reader function.  The created KsbaReader object
576    is also returned, but the caller must not call the
577    ksba_reader_release function on.  If ALLOW_MULTI_PEM is true, the
578    reader expects that the caller uses ksba_reader_clear after EOF
579    until no more objects were found. */
580 int
581 gpgsm_create_reader (Base64Context *ctx,
582                      ctrl_t ctrl, FILE *fp, int allow_multi_pem,
583                      ksba_reader_t *r_reader)
584 {
585   int rc;
586   ksba_reader_t r;
587
588   *r_reader = NULL;
589   *ctx = xtrycalloc (1, sizeof **ctx);
590   if (!*ctx)
591     return out_of_core ();
592   (*ctx)->u.rparm.allow_multi_pem = allow_multi_pem;
593
594   rc = ksba_reader_new (&r);
595   if (rc)
596     {
597       xfree (*ctx); *ctx = NULL;
598       return rc;
599     }
600
601   (*ctx)->u.rparm.fp = fp;
602   if (ctrl->is_pem)
603     {
604       (*ctx)->u.rparm.assume_pem = 1;
605       (*ctx)->u.rparm.assume_base64 = 1;
606       rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm);
607     }
608   else if (ctrl->is_base64)
609     {
610       (*ctx)->u.rparm.assume_base64 = 1;
611       rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm);
612     }
613   else if (ctrl->autodetect_encoding)
614     {
615       (*ctx)->u.rparm.autodetect = 1;
616       rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm);
617     }
618   else
619       rc = ksba_reader_set_cb (r, simple_reader_cb, &(*ctx)->u.rparm);
620
621   if (rc)
622     {
623       ksba_reader_release (r);
624       xfree (*ctx); *ctx = NULL;
625       return rc;
626     }
627
628   (*ctx)->u2.reader = r;
629   *r_reader = r;
630   return 0;
631 }
632
633
634 int
635 gpgsm_reader_eof_seen (Base64Context ctx)
636 {
637   return ctx && ctx->u.rparm.eof_seen;
638 }
639
640 void
641 gpgsm_destroy_reader (Base64Context ctx)
642 {
643   if (!ctx)
644     return;
645
646   ksba_reader_release (ctx->u2.reader);  
647   xfree (ctx);
648 }
649
650
651 \f
652 /* Create a writer for the given stream FP or STREAM.  Depending on
653    the control information an output encoding is automagically
654    choosen.  The function returns a Base64Context object which must be
655    passed to the gpgme_destroy_writer function.  The created
656    KsbaWriter object is also returned, but the caller must not call
657    the ksba_reader_release function on. */
658 int
659 gpgsm_create_writer (Base64Context *ctx,
660                      ctrl_t ctrl, FILE *fp, estream_t stream,
661                      ksba_writer_t *r_writer)
662 {
663   int rc;
664   ksba_writer_t w;
665
666   *r_writer = NULL;
667   *ctx = xtrycalloc (1, sizeof **ctx);
668   if (!*ctx)
669     return out_of_core ();
670
671   rc = ksba_writer_new (&w);
672   if (rc)
673     {
674       xfree (*ctx); *ctx = NULL;
675       return rc;
676     }
677
678   if (ctrl->create_pem || ctrl->create_base64)
679     {
680       (*ctx)->u.wparm.fp = fp;
681       (*ctx)->u.wparm.stream = stream;
682       if (ctrl->create_pem)
683         (*ctx)->u.wparm.pem_name = ctrl->pem_name? ctrl->pem_name
684                                                  : "CMS OBJECT";
685       rc = ksba_writer_set_cb (w, base64_writer_cb, &(*ctx)->u.wparm);
686     }
687   else if (stream)
688     {
689       (*ctx)->u.wparm.fp = fp;
690       (*ctx)->u.wparm.stream = stream;
691       rc = ksba_writer_set_cb (w, plain_writer_cb, &(*ctx)->u.wparm);
692     }
693   else
694     rc = ksba_writer_set_file (w, fp);
695
696   if (rc)
697     {
698       ksba_writer_release (w);
699       xfree (*ctx); *ctx = NULL;
700       return rc;
701     }
702
703   (*ctx)->u2.writer = w;
704   *r_writer = w;
705   return 0;
706 }
707
708
709 int
710 gpgsm_finish_writer (Base64Context ctx)
711 {
712   struct writer_cb_parm_s *parm;
713   
714   if (!ctx)
715     return gpg_error (GPG_ERR_INV_VALUE);
716   parm = &ctx->u.wparm;
717   if (parm->did_finish)
718     return 0; /* Already done. */
719   parm->did_finish = 1;
720   if (!parm->fp && !parm->stream)
721     return 0; /* Callback was not used.  */
722   return base64_finish_write (parm);
723 }
724
725 void
726 gpgsm_destroy_writer (Base64Context ctx)
727 {
728   if (!ctx)
729     return;
730
731   ksba_writer_release (ctx->u2.writer);
732   xfree (ctx);
733 }