mutt stable branch with some hacks
at jcs 208 lines 4.5 kB view raw
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 38static const struct 39{ 40 short id; 41 const char *name; 42} 43HashAlgorithms[] = 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 58static 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 68static 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 138static 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 161static short pgp_find_hash (const char *fname) 162{ 163 FILE *in = NULL; 164 FILE *out = NULL; 165 BUFFER *tempfile = NULL; 166 unsigned char *p; 167 size_t l; 168 short rv = -1; 169 170 tempfile = mutt_buffer_pool_get (); 171 mutt_buffer_mktemp (tempfile); 172 if ((out = safe_fopen (mutt_b2s (tempfile), "w+")) == NULL) 173 { 174 mutt_perror (mutt_b2s (tempfile)); 175 goto bye; 176 } 177 unlink (mutt_b2s (tempfile)); 178 179 if ((in = fopen (fname, "r")) == NULL) 180 { 181 mutt_perror (fname); 182 goto bye; 183 } 184 185 pgp_dearmor (in, out); 186 rewind (out); 187 188 if ((p = pgp_read_packet (out, &l)) != NULL) 189 { 190 rv = pgp_mic_from_packet (p, l); 191 } 192 else 193 { 194 dprint (1, (debugfile, "pgp_find_hash: No packet.\n")); 195 } 196 197bye: 198 mutt_buffer_pool_release (&tempfile); 199 safe_fclose (&in); 200 safe_fclose (&out); 201 pgp_release_packet (); 202 return rv; 203} 204 205const char *pgp_micalg (const char *fname) 206{ 207 return pgp_hash_to_micalg (pgp_find_hash (fname)); 208}