Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 212 lines (177 sloc) 4.444 kb
14c2920 Imported Upstream version 1.5.18
Antonio Radici authored
1 /*
2 * Copyright (C) 2001 Thomas Roessler <roessler@does-not-exist.org>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public
15 * License along with this program; if not, write to the Free
16 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301, USA.
18 */
19
20 /* This module peeks at a PGP signature and figures out the hash
21 * algorithm.
22 */
23
24 #if HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include "mutt.h"
29 #include "pgp.h"
30 #include "pgppacket.h"
31 #include "charset.h"
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37
38 static struct
39 {
40 short id;
41 const char *name;
42 }
43 HashAlgorithms[] =
44 {
45 { 1, "pgp-md5" },
46 { 2, "pgp-sha1" },
47 { 3, "pgp-ripemd160" },
48 { 5, "pgp-md2" },
49 { 6, "pgp-tiger192" },
50 { 7, "pgp-haval-5-160" },
51 { 8, "pgp-sha256" },
52 { 9, "pgp-sha384" },
53 { 10, "pgp-sha512" },
54 { 11, "pgp-sha224" },
55 { -1, NULL }
56 };
57
58 static const char *pgp_hash_to_micalg (short id)
59 {
60 int i;
61
62 for (i = 0; HashAlgorithms[i].id >= 0; i++)
63 if (HashAlgorithms[i].id == id)
64 return HashAlgorithms[i].name;
65 return "x-unknown";
66 }
67
68 static void pgp_dearmor (FILE *in, FILE *out)
69 {
70 char line[HUGE_STRING];
71 LOFF_T start;
72 LOFF_T end;
73 char *r;
74
75 STATE state;
76
77 memset (&state, 0, sizeof (STATE));
78 state.fpin = in;
79 state.fpout = out;
80
81 /* find the beginning of ASCII armor */
82
83 while ((r = fgets (line, sizeof (line), in)) != NULL)
84 {
85 if (!strncmp (line, "-----BEGIN", 10))
86 break;
87 }
88 if (r == NULL)
89 {
90 dprint (1, (debugfile, "pgp_dearmor: Can't find begin of ASCII armor.\n"));
91 return;
92 }
93
94 /* skip the armor header */
95
96 while ((r = fgets (line, sizeof (line), in)) != NULL)
97 {
98 SKIPWS (r);
99 if (!*r) break;
100 }
101 if (r == NULL)
102 {
103 dprint (1, (debugfile, "pgp_dearmor: Armor header doesn't end.\n"));
104 return;
105 }
106
107 /* actual data starts here */
108 start = ftello (in);
109
110 /* find the checksum */
111
112 while ((r = fgets (line, sizeof (line), in)) != NULL)
113 {
114 if (*line == '=' || !strncmp (line, "-----END", 8))
115 break;
116 }
117 if (r == NULL)
118 {
119 dprint (1, (debugfile, "pgp_dearmor: Can't find end of ASCII armor.\n"));
120 return;
121 }
122
123 if ((end = ftello (in) - strlen (line)) < start)
124 {
125 dprint (1, (debugfile, "pgp_dearmor: end < start???\n"));
126 return;
127 }
128
129 if (fseeko (in, start, SEEK_SET) == -1)
130 {
131 dprint (1, (debugfile, "pgp_dearmor: Can't seekto start.\n"));
132 return;
133 }
134
135 mutt_decode_base64 (&state, end - start, 0, (iconv_t) -1);
136 }
137
138 static short pgp_mic_from_packet (unsigned char *p, size_t len)
139 {
140 /* is signature? */
141 if ((p[0] & 0x3f) != PT_SIG)
142 {
143 dprint (1, (debugfile, "pgp_mic_from_packet: tag = %d, want %d.\n",
144 p[0]&0x3f, PT_SIG));
145 return -1;
146 }
147
148 if (len >= 18 && p[1] == 3)
149 /* version 3 signature */
150 return (short) p[17];
151 else if (len >= 5 && p[1] == 4)
152 /* version 4 signature */
153 return (short) p[4];
154 else
155 {
156 dprint (1, (debugfile, "pgp_mic_from_packet: Bad signature packet.\n"));
157 return -1;
158 }
159 }
160
161 static short pgp_find_hash (const char *fname)
162 {
163 FILE *in = NULL;
164 FILE *out = NULL;
165
166 char tempfile[_POSIX_PATH_MAX];
167
168 unsigned char *p;
169 size_t l;
170
171 short rv = -1;
172
594a6a4 Imported Upstream version 1.5.21
Antonio Radici authored
173 mutt_mktemp (tempfile, sizeof (tempfile));
14c2920 Imported Upstream version 1.5.18
Antonio Radici authored
174 if ((out = safe_fopen (tempfile, "w+")) == NULL)
175 {
176 mutt_perror (tempfile);
177 goto bye;
178 }
179 unlink (tempfile);
180
181 if ((in = fopen (fname, "r")) == NULL)
182 {
183 mutt_perror (fname);
184 goto bye;
185 }
186
187 pgp_dearmor (in, out);
188 rewind (out);
189
190 if ((p = pgp_read_packet (out, &l)) != NULL)
191 {
192 rv = pgp_mic_from_packet (p, l);
193 }
194 else
195 {
196 dprint (1, (debugfile, "pgp_find_hash: No packet.\n"));
197 }
198
199 bye:
200
201 safe_fclose (&in);
202 safe_fclose (&out);
203 pgp_release_packet ();
204 return rv;
205 }
206
207 const char *pgp_micalg (const char *fname)
208 {
209 return pgp_hash_to_micalg (pgp_find_hash (fname));
210 }
211
Something went wrong with that request. Please try again.