X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=lib-crypt%2Fpgpmicalg.c;fp=lib-crypt%2Fpgpmicalg.c;h=1c322be064d206c878357b0f49dd69aa23d135c4;hp=0000000000000000000000000000000000000000;hb=4761fa78a6dfc9437caa6e6e0aac806e50e01c83;hpb=b8c71f93b0296f815a6538182343ba67e88c0012 diff --git a/lib-crypt/pgpmicalg.c b/lib-crypt/pgpmicalg.c new file mode 100644 index 0000000..1c322be --- /dev/null +++ b/lib-crypt/pgpmicalg.c @@ -0,0 +1,190 @@ +/* + * Copyright notice from original mutt: + * Copyright (C) 2001 Thomas Roessler + * + * This file is part of mutt-ng, see http://www.muttng.org/. + * It's licensed under the GNU General Public License, + * please see the file GPL in the top level source directory. + */ + +/* This module peeks at a PGP signature and figures out the hash + * algorithm. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "mutt.h" +#include "handler.h" +#include "pgp.h" +#include "pgppacket.h" +#include "charset.h" + +#include +#include +#include +#include + +#include + +#include + +#include "lib/debug.h" + +static struct { + short id; + const char *name; +} HashAlgorithms[] = { + { + 1, "pgp-md5"}, { + 2, "pgp-sha1"}, { + 3, "pgp-ripemd160"}, { + 5, "pgp-md2"}, { + 6, "pgp-tiger192"}, { + 7, "pgp-haval-5-160"}, { + 8, "pgp-sha256"}, { + 9, "pgp-sha384"}, { + 10, "pgp-sha512"}, { + -1, NULL} +}; + +static const char *pgp_hash_to_micalg (short id) +{ + int i; + + for (i = 0; HashAlgorithms[i].id >= 0; i++) + if (HashAlgorithms[i].id == id) + return HashAlgorithms[i].name; + return "x-unknown"; +} + +static void pgp_dearmor (FILE * in, FILE * out) +{ + char line[HUGE_STRING]; + off_t start; + off_t end; + char *r; + + STATE state; + + p_clear(&state, 1); + state.fpin = in; + state.fpout = out; + + /* find the beginning of ASCII armor */ + + while ((r = fgets (line, sizeof (line), in)) != NULL) { + if (!strncmp (line, "-----BEGIN", 10)) + break; + } + if (r == NULL) { + debug_print (1, ("Can't find begin of ASCII armor.\n")); + return; + } + + /* skip the armor header */ + + while ((r = fgets (line, sizeof (line), in)) != NULL) { + r = vskipspaces(r); + if (!*r) + break; + } + if (r == NULL) { + debug_print (1, ("Armor header doesn't end.\n")); + return; + } + + /* actual data starts here */ + start = ftello (in); + + /* find the checksum */ + + while ((r = fgets (line, sizeof (line), in)) != NULL) { + if (*line == '=' || !strncmp (line, "-----END", 8)) + break; + } + if (r == NULL) { + debug_print (1, ("Can't find end of ASCII armor.\n")); + return; + } + + if ((end = ftello (in) - m_strlen(line)) < start) { + debug_print (1, ("end < start???\n")); + return; + } + + if (fseeko (in, start, SEEK_SET) == -1) { + debug_print (1, ("Can't seekto start.\n")); + return; + } + + mutt_decode_base64 (&state, end - start, 0, (iconv_t) - 1); +} + +static short pgp_mic_from_packet (unsigned char *p, size_t len) +{ + /* is signature? */ + if ((p[0] & 0x3f) != PT_SIG) { + debug_print (1, ("tag = %d, want %d.\n", p[0] & 0x3f, PT_SIG)); + return -1; + } + + if (len >= 18 && p[1] == 3) + /* version 3 signature */ + return (short) p[17]; + else if (len >= 5 && p[1] == 4) + /* version 4 signature */ + return (short) p[4]; + else { + debug_print (1, ("Bad signature packet.\n")); + return -1; + } +} + +static short pgp_find_hash (const char *fname) +{ + FILE *in = NULL; + FILE *out = NULL; + + char tempfile[_POSIX_PATH_MAX]; + + unsigned char *p; + size_t l; + + short rv = -1; + + mutt_mktemp (tempfile); + if ((out = safe_fopen (tempfile, "w+")) == NULL) { + mutt_perror (tempfile); + goto bye; + } + unlink (tempfile); + + if ((in = fopen (fname, "r")) == NULL) { + mutt_perror (fname); + goto bye; + } + + pgp_dearmor (in, out); + rewind (out); + + if ((p = pgp_read_packet (out, &l)) != NULL) { + rv = pgp_mic_from_packet (p, l); + } + else { + debug_print (1, ("No packet.\n")); + } + +bye: + + safe_fclose (&in); + safe_fclose (&out); + pgp_release_packet (); + return rv; +} + +const char *pgp_micalg (const char *fname) +{ + return pgp_hash_to_micalg (pgp_find_hash (fname)); +}