~ubuntu-branches/ubuntu/oneiric/gnupg2/oneiric-updates

« back to all changes in this revision

Viewing changes to sm/certdump.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-10-04 10:25:53 UTC
  • mfrom: (5.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081004102553-fv62pp8dsitxli47
Tags: 2.0.9-3.1
* Non-maintainer upload.
* agent/gpg-agent.c: Deinit the threading library before exec'ing
  the command to run in --daemon mode. And because that still doesn't
  restore the sigprocmask, do that manually. Closes: #499569

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* certdump.c - Dump a certificate for debugging
2
 
 *      Copyright (C) 2001, 2004 Free Software Foundation, Inc.
 
2
 * Copyright (C) 2001, 2004, 2007 Free Software Foundation, Inc.
3
3
 *
4
4
 * This file is part of GnuPG.
5
5
 *
6
6
 * GnuPG is free software; you can redistribute it and/or modify
7
7
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * the Free Software Foundation; either version 3 of the License, or
9
9
 * (at your option) any later version.
10
10
 *
11
11
 * GnuPG is distributed in the hope that it will be useful,
14
14
 * GNU General Public License for more details.
15
15
 *
16
16
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
17
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19
18
 */
20
19
 
21
20
#include <config.h>
40
39
#include "keydb.h"
41
40
#include "i18n.h"
42
41
 
 
42
#ifdef HAVE_FOPENCOOKIE
 
43
typedef ssize_t my_funopen_hook_ret_t;
 
44
typedef size_t  my_funopen_hook_size_t;
 
45
#else
 
46
typedef int     my_funopen_hook_ret_t;
 
47
typedef int     my_funopen_hook_size_t;
 
48
#endif
 
49
 
 
50
 
43
51
struct dn_array_s {
44
52
  char *key;
45
53
  char *value;
48
56
};
49
57
 
50
58
 
51
 
/* print the first element of an S-Expression */
 
59
/* Print the first element of an S-Expression. */
52
60
void
53
 
gpgsm_print_serial (FILE *fp, ksba_const_sexp_t sn)
 
61
gpgsm_print_serial (estream_t fp, ksba_const_sexp_t sn)
54
62
{
55
63
  const char *p = (const char *)sn;
56
64
  unsigned long n;
57
65
  char *endp;
58
66
 
59
67
  if (!p)
60
 
    fputs (_("none"), fp);
 
68
    es_fputs (_("none"), fp);
61
69
  else if (*p != '(')
62
 
    fputs ("[Internal error - not an S-expression]", fp);
 
70
    es_fputs ("[Internal error - not an S-expression]", fp);
63
71
  else
64
72
    {
65
73
      p++;
66
74
      n = strtoul (p, &endp, 10);
67
75
      p = endp;
68
 
      if (*p!=':')
69
 
        fputs ("[Internal Error - invalid S-expression]", fp);
 
76
      if (*p++ != ':')
 
77
        es_fputs ("[Internal Error - invalid S-expression]", fp);
70
78
      else
71
 
        {
72
 
          for (p++; n; n--, p++)
73
 
            fprintf (fp, "%02X", *(const unsigned char*)p);
74
 
        }
 
79
        es_write_hexstring (fp, p, n, 0, NULL);
75
80
    }
76
81
}
77
82
 
140
145
 
141
146
 
142
147
void
143
 
gpgsm_print_time (FILE *fp, ksba_isotime_t t)
 
148
gpgsm_print_time (estream_t fp, ksba_isotime_t t)
144
149
{
145
150
  if (!t || !*t)
146
 
    fputs (_("none"), fp);
 
151
    es_fputs (_("none"), fp);
147
152
  else
148
 
    fprintf (fp, "%.4s-%.2s-%.2s %.2s:%.2s:%s", t, t+4, t+6, t+9, t+11, t+13);
 
153
    es_fprintf (fp, "%.4s-%.2s-%.2s %.2s:%.2s:%s",
 
154
                t, t+4, t+6, t+9, t+11, t+13);
149
155
}
150
156
 
 
157
 
151
158
void
152
159
gpgsm_dump_time (ksba_isotime_t t)
153
160
{
237
244
}
238
245
 
239
246
 
 
247
/* Return a new string holding the format serial number and issuer
 
248
   ("#SN/issuer").  No filtering on invalid characters is done.
 
249
   Caller must release the string.  On memory failure NULL is
 
250
   returned.  */
 
251
char *
 
252
gpgsm_format_sn_issuer (ksba_sexp_t sn, const char *issuer)
 
253
{
 
254
  char *p, *p1;
 
255
 
 
256
  if (sn && issuer)
 
257
    {
 
258
      p1 = gpgsm_format_serial (sn);
 
259
      if (!p1)
 
260
        p = xtrystrdup ("[invalid SN]");
 
261
      else
 
262
        {
 
263
          p = xtrymalloc (strlen (p1) + strlen (issuer) + 2 + 1);
 
264
          if (p)
 
265
            {
 
266
              *p = '#';
 
267
              strcpy (stpcpy (stpcpy (p+1, p1),"/"), issuer);
 
268
            }
 
269
          xfree (p1);
 
270
        }
 
271
    }
 
272
  else
 
273
    p = xtrystrdup ("[invalid SN/issuer]");
 
274
  return p;
 
275
}
 
276
 
 
277
 
 
278
/* Log the certificate's name in "#SN/ISSUERDN" format along with
 
279
   TEXT. */
 
280
void 
 
281
gpgsm_cert_log_name (const char *text, ksba_cert_t cert)
 
282
{
 
283
  log_info ("%s", text? text:"certificate" );
 
284
  if (cert)
 
285
    {
 
286
      ksba_sexp_t sn;
 
287
      char *p;
 
288
 
 
289
      p = ksba_cert_get_issuer (cert, 0);
 
290
      sn = ksba_cert_get_serial (cert);
 
291
      if (p && sn)
 
292
        {
 
293
          log_printf (" #");
 
294
          gpgsm_dump_serial (sn);
 
295
          log_printf ("/");
 
296
          gpgsm_dump_string (p);
 
297
        }
 
298
      else
 
299
        log_printf (" [invalid]");
 
300
      ksba_free (sn);
 
301
      xfree (p);
 
302
    }
 
303
  log_printf ("\n");
 
304
}
 
305
 
 
306
 
 
307
 
 
308
 
 
309
 
240
310
 
241
311
/* helper for the rfc2253 string parser */
242
312
static const unsigned char *
338
408
          else if (*s == '\"')
339
409
            return NULL; /* invalid encoding */
340
410
          else if (*s == ',' || *s == '=' || *s == '+'
341
 
                   || *s == '<' || *s == '>' || *s == '#' || *s == ';' )
 
411
                   || *s == '<' || *s == '>' || *s == ';' )
342
412
            break; 
343
413
          else
344
414
            n++;
430
500
}
431
501
 
432
502
 
 
503
/* Print a DN part to STREAM or if STREAM is NULL to FP. */
433
504
static void
434
 
print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key, int translate)
 
505
print_dn_part (FILE *fp, estream_t stream,
 
506
               struct dn_array_s *dn, const char *key, int translate)
435
507
{
436
508
  struct dn_array_s *first_dn = dn;
437
509
 
449
521
        next:
450
522
          if (!dn->done && dn->value && *dn->value)
451
523
            {
452
 
              fprintf (fp, "/%s=", dn->key);
453
 
              if (translate)
454
 
                print_sanitized_utf8_string (fp, dn->value, '/');
 
524
              if (stream)
 
525
                {
 
526
                  es_fprintf (stream, "/%s=", dn->key);
 
527
                  if (translate)
 
528
                    es_write_sanitized_utf8_buffer (stream, dn->value,
 
529
                                                    strlen (dn->value),
 
530
                                                    "/", NULL);
 
531
                  else
 
532
                    es_write_sanitized (stream, dn->value, strlen (dn->value),
 
533
                                        "/", NULL);
 
534
                }
455
535
              else
456
 
                print_sanitized_string (fp, dn->value, '/');
 
536
                {
 
537
                  fprintf (fp, "/%s=", dn->key);
 
538
                  if (translate)
 
539
                    print_sanitized_utf8_string (fp, dn->value, '/');
 
540
                  else
 
541
                    print_sanitized_string (fp, dn->value, '/');
 
542
                }
457
543
            }
458
544
          dn->done = 1;
459
545
          if (dn > first_dn && dn[-1].multivalued)
468
554
/* Print all parts of a DN in a "standard" sequence.  We first print
469
555
   all the known parts, followed by the uncommon ones */
470
556
static void
471
 
print_dn_parts (FILE *fp, struct dn_array_s *dn, int translate)
 
557
print_dn_parts (FILE *fp, estream_t stream,
 
558
                struct dn_array_s *dn, int translate)
472
559
{
473
560
  const char *stdpart[] = {
474
561
    "CN", "OU", "O", "STREET", "L", "ST", "C", "EMail", NULL 
476
563
  int i;
477
564
  
478
565
  for (i=0; stdpart[i]; i++)
479
 
      print_dn_part (fp, dn, stdpart[i], translate);
 
566
      print_dn_part (fp, stream, dn, stdpart[i], translate);
480
567
 
481
568
  /* Now print the rest without any specific ordering */
482
569
  for (; dn->key; dn++)
483
 
    print_dn_part (fp, dn, dn->key, translate);
 
570
    print_dn_part (fp, stream, dn, dn->key, translate);
484
571
}
485
572
 
486
573
 
529
616
  gcry_sexp_release (sexp);
530
617
}
531
618
 
 
619
/* Print the S-Expression in BUF to extended STREAM, which has a valid
 
620
   length of BUFLEN, as a human readable string in one line to FP. */
 
621
static void
 
622
pretty_es_print_sexp (estream_t fp, const unsigned char *buf, size_t buflen)
 
623
{
 
624
  size_t len;
 
625
  gcry_sexp_t sexp;
 
626
  char *result, *p;
 
627
 
 
628
  if ( gcry_sexp_sscan (&sexp, NULL, (const char*)buf, buflen) )
 
629
    {
 
630
      es_fputs (_("[Error - invalid encoding]"), fp);
 
631
      return;
 
632
    }
 
633
  len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
 
634
  assert (len);
 
635
  result = xtrymalloc (len);
 
636
  if (!result)
 
637
    {
 
638
      es_fputs (_("[Error - out of core]"), fp);
 
639
      gcry_sexp_release (sexp);
 
640
      return;
 
641
    }
 
642
  len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, len);
 
643
  assert (len);
 
644
  for (p = result; len; len--, p++)
 
645
    {
 
646
      if (*p == '\n')
 
647
        {
 
648
          if (len > 1) /* Avoid printing the trailing LF. */
 
649
            es_fputs ("\\n", fp);
 
650
        }
 
651
      else if (*p == '\r')
 
652
        es_fputs ("\\r", fp);
 
653
      else if (*p == '\v')
 
654
        es_fputs ("\\v", fp);
 
655
      else if (*p == '\t')
 
656
        es_fputs ("\\t", fp);
 
657
      else
 
658
        es_putc (*p, fp);
 
659
    }
 
660
  xfree (result);
 
661
  gcry_sexp_release (sexp);
 
662
}
 
663
 
 
664
 
 
665
 
532
666
 
533
667
void
534
668
gpgsm_print_name2 (FILE *fp, const char *name, int translate)
566
700
        fputs (_("[Error - invalid DN]"), fp);
567
701
      else 
568
702
        {
569
 
          print_dn_parts (fp, dn, translate);          
 
703
          print_dn_parts (fp, NULL, dn, translate);          
570
704
          for (i=0; dn[i].key; i++)
571
705
            {
572
706
              xfree (dn[i].key);
585
719
}
586
720
 
587
721
 
 
722
/* This is avariant of gpgsm_print_name sending it output to an estream. */
 
723
void
 
724
gpgsm_es_print_name (estream_t fp, const char *name)
 
725
{
 
726
  const unsigned char *s = (const unsigned char *)name;
 
727
  int i;
 
728
 
 
729
  if (!s)
 
730
    {
 
731
      es_fputs (_("[Error - No name]"), fp);
 
732
    }
 
733
  else if (*s == '<')
 
734
    {
 
735
      const char *s2 = strchr ( (char*)s+1, '>');
 
736
 
 
737
      if (s2)
 
738
        es_write_sanitized_utf8_buffer (fp, s + 1, s2 - (char*)s - 1,
 
739
                                        NULL, NULL);
 
740
    }
 
741
  else if (*s == '(')
 
742
    {
 
743
      pretty_es_print_sexp (fp, s, gcry_sexp_canon_len (s, 0, NULL, NULL));
 
744
    }
 
745
  else if (!((*s >= '0' && *s < '9')
 
746
             || (*s >= 'A' && *s <= 'Z')
 
747
             || (*s >= 'a' && *s <= 'z')))
 
748
    es_fputs (_("[Error - invalid encoding]"), fp);
 
749
  else
 
750
    {
 
751
      struct dn_array_s *dn = parse_dn (s);
 
752
 
 
753
      if (!dn)
 
754
        es_fputs (_("[Error - invalid DN]"), fp);
 
755
      else 
 
756
        {
 
757
          print_dn_parts (NULL, fp, dn, 1);          
 
758
          for (i=0; dn[i].key; i++)
 
759
            {
 
760
              xfree (dn[i].key);
 
761
              xfree (dn[i].value);
 
762
            }
 
763
          xfree (dn);
 
764
        }
 
765
    }
 
766
}
 
767
 
 
768
 
 
769
 
 
770
 
 
771
#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
588
772
/* A cookie structure used for the memory stream. */
589
773
struct format_name_cookie 
590
774
{
595
779
};
596
780
 
597
781
/* The writer function for the memory stream. */
598
 
static int 
599
 
format_name_writer (void *cookie, const char *buffer, size_t size)
 
782
static my_funopen_hook_ret_t
 
783
format_name_writer (void *cookie, const char *buffer,
 
784
                    my_funopen_hook_size_t size)
600
785
{
601
786
  struct format_name_cookie *c = cookie;
602
787
  char *p;
610
795
      c->error = errno;
611
796
      xfree (c->buffer);
612
797
      errno = c->error;
613
 
      return -1;
 
798
      return (my_funopen_hook_ret_t)(-1);
614
799
    }
615
800
  c->buffer = p;
616
801
  memcpy (p + c->len, buffer, size);
617
802
  c->len += size;
618
803
  p[c->len] = 0; /* Terminate string. */ 
619
804
 
620
 
  return size;
 
805
  return (my_funopen_hook_ret_t)size;
621
806
}
 
807
#endif /*HAVE_FOPENCOOKIE || HAVE_FUNOPEN*/
 
808
 
622
809
 
623
810
/* Format NAME which is expected to be in rfc2253 format into a better
624
811
   human readable format. Caller must free the returned string.  NULL
674
861
}
675
862
 
676
863
 
 
864
/* Return fingerprint and a percent escaped name in a human readable
 
865
   format suitable for status messages like GOODSIG.  May return NULL
 
866
   on error (out of core). */
 
867
char *
 
868
gpgsm_fpr_and_name_for_status (ksba_cert_t cert)
 
869
{
 
870
  char *fpr, *name, *p;
 
871
  char *buffer;
 
872
 
 
873
  fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
 
874
  if (!fpr)
 
875
    return NULL;
 
876
  
 
877
  name = ksba_cert_get_subject (cert, 0);
 
878
  if (!name)
 
879
    {
 
880
      xfree (fpr);
 
881
      return NULL;
 
882
    }
 
883
 
 
884
  p = gpgsm_format_name2 (name, 0);
 
885
  ksba_free (name);
 
886
  name = p;
 
887
  if (!name)
 
888
    {
 
889
      xfree (fpr);
 
890
      return NULL;
 
891
    }
 
892
 
 
893
  buffer = xtrymalloc (strlen (fpr) + 1 + 3*strlen (name) + 1);
 
894
  if (buffer)
 
895
    {
 
896
      const char *s;
 
897
 
 
898
      p = stpcpy (stpcpy (buffer, fpr), " ");
 
899
      for (s = name; *s; s++)
 
900
        {
 
901
          if (*s < ' ')
 
902
            {
 
903
              sprintf (p, "%%%02X", *(const unsigned char*)s);
 
904
              p += 3;
 
905
            }
 
906
          else
 
907
            *p++ = *s;
 
908
        }
 
909
      *p = 0;
 
910
    }
 
911
  xfree (fpr);
 
912
  xfree (name);
 
913
  return buffer;
 
914
}
 
915
 
 
916
 
677
917
/* Create a key description for the CERT, this may be passed to the
678
918
   pinentry.  The caller must free the returned string. NULL may be
679
919
   returned on error. */
685
925
  const char *s;
686
926
  ksba_isotime_t t;
687
927
  char created[20];
 
928
  char expires[20];
688
929
  char *sn;
689
930
  ksba_sexp_t sexp;
690
 
  char *orig_codeset = NULL;
 
931
  char *orig_codeset;
691
932
 
692
933
  name = ksba_cert_get_subject (cert, 0);
693
934
  subject = name? gpgsm_format_name2 (name, 0) : NULL;
698
939
  ksba_free (sexp);
699
940
 
700
941
  ksba_cert_get_validity (cert, 0, t);
701
 
  if (t && *t)
 
942
  if (*t)
702
943
    sprintf (created, "%.4s-%.2s-%.2s", t, t+4, t+6);
703
944
  else
704
945
    *created = 0;
705
 
 
706
 
 
707
 
#ifdef ENABLE_NLS
708
 
  /* The Assuan agent protocol requires us to transmit utf-8 strings */
709
 
  orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL);
710
 
#ifdef HAVE_LANGINFO_CODESET
711
 
  if (!orig_codeset)
712
 
    orig_codeset = nl_langinfo (CODESET);
713
 
#endif
714
 
  if (orig_codeset)
715
 
    { /* We only switch when we are able to restore the codeset later.
716
 
         Note that bind_textdomain_codeset does only return on memory
717
 
         errors but not if a codeset is not available.  Thus we don't
718
 
         bother printing a diagnostic here. */
719
 
      orig_codeset = xstrdup (orig_codeset);
720
 
      if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8"))
721
 
        orig_codeset = NULL; 
722
 
    }
723
 
#endif
724
 
 
 
946
  ksba_cert_get_validity (cert, 1, t);
 
947
  if (*t)
 
948
    sprintf (expires, "%.4s-%.2s-%.2s", t, t+4, t+6);
 
949
  else
 
950
    *expires = 0;
 
951
 
 
952
  orig_codeset = i18n_switchto_utf8 ();
725
953
 
726
954
  rc = asprintf (&name,
727
955
                 _("Please enter the passphrase to unlock the"
728
 
                   " secret key for:\n"
 
956
                   " secret key for the X.509 certificate:\n"
729
957
                   "\"%s\"\n"
730
 
                   "S/N %s, ID %08lX, created %s" ),
 
958
                   "S/N %s, ID 0x%08lX,\n"
 
959
                   "created %s, expires %s.\n" ),
731
960
                 subject? subject:"?",
732
961
                 sn? sn: "?",
733
962
                 gpgsm_get_short_fingerprint (cert),
734
 
                 created);
 
963
                 created, expires);
735
964
 
736
 
#ifdef ENABLE_NLS
737
 
  if (orig_codeset)
738
 
    bind_textdomain_codeset (PACKAGE_GT, orig_codeset);
739
 
#endif
740
 
  xfree (orig_codeset);
 
965
  i18n_switchback (orig_codeset);
741
966
 
742
967
  if (rc < 0)
743
968
    {
769
994
 
770
995
  return buffer;
771
996
}
 
997