⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pgp.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 1996,1997 Michael R. Elkins <me@mutt.org> * Copyright (C) 1998,1999 Thomas Roessler <roessler@does-not-exist.org> * Copyright (C) 2004 g10 Code GmbH * *     This program is free software; you can redistribute it and/or modify *     it under the terms of the GNU General Public License as published by *     the Free Software Foundation; either version 2 of the License, or *     (at your option) any later version. *  *     This program is distributed in the hope that it will be useful, *     but WITHOUT ANY WARRANTY; without even the implied warranty of *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *     GNU General Public License for more details. *  *     You should have received a copy of the GNU General Public License *     along with this program; if not, write to the Free Software *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. */ /* * This file contains all of the PGP routines necessary to sign, encrypt, * verify and decrypt PGP messages in either the new PGP/MIME format, or * in the older Application/Pgp format.  It also contains some code to * cache the user's passphrase for repeat use when decrypting or signing * a message. */#if HAVE_CONFIG_H# include "config.h"#endif#include "mutt.h"#include "mutt_curses.h"#include "pgp.h"#include "mime.h"#include "copy.h"#include <sys/wait.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <sys/stat.h>#include <errno.h>#include <ctype.h>#ifdef HAVE_LOCALE_H#include <locale.h>#endif#ifdef HAVE_SYS_TIME_H# include <sys/time.h>#endif#ifdef HAVE_SYS_RESOURCE_H# include <sys/resource.h>#endif#ifdef CRYPT_BACKEND_CLASSIC_PGP#include "mutt_crypt.h"#include "mutt_menu.h"char PgpPass[LONG_STRING];time_t PgpExptime = 0; /* when does the cached passphrase expire? */void pgp_void_passphrase (void){  memset (PgpPass, 0, sizeof (PgpPass));  PgpExptime = 0;}int pgp_valid_passphrase (void){  time_t now = time (NULL);  if (pgp_use_gpg_agent())    {      *PgpPass = 0;      return 1; /* handled by gpg-agent */    }  if (now < PgpExptime)    /* Use cached copy.  */    return 1;    pgp_void_passphrase ();  if (mutt_get_password (_("Enter PGP passphrase:"), PgpPass, sizeof (PgpPass)) == 0)    {      PgpExptime = time (NULL) + PgpTimeout;      return (1);    }  else    PgpExptime = 0;  return 0;}void pgp_forget_passphrase (void){  pgp_void_passphrase ();  mutt_message _("PGP passphrase forgotten.");}int pgp_use_gpg_agent (void){  char *tty;  if (!option (OPTUSEGPGAGENT) || !getenv ("GPG_AGENT_INFO"))    return 0;  if ((tty = ttyname(0)))    setenv("GPG_TTY", tty, 0);  return 1;}char *pgp_keyid(pgp_key_t k){  if((k->flags & KEYFLAG_SUBKEY) && k->parent && option(OPTPGPIGNORESUB))    k = k->parent;  return _pgp_keyid(k);}char *_pgp_keyid(pgp_key_t k){  if(option(OPTPGPLONGIDS))    return k->keyid;  else    return (k->keyid + 8);}/* ---------------------------------------------------------------------------- * Routines for handing PGP input. *//* Copy PGP output messages and look for signs of a good signature */static int pgp_copy_checksig (FILE *fpin, FILE *fpout){  int rv = -1;  if (PgpGoodSign.pattern)  {    char *line = NULL;    int lineno = 0;    size_t linelen;        while ((line = mutt_read_line (line, &linelen, fpin, &lineno)) != NULL)    {      if (regexec (PgpGoodSign.rx, line, 0, NULL, 0) == 0)      {	dprint (2, (debugfile, "pgp_copy_checksig: \"%s\" matches regexp.\n",		    line));	rv = 0;      }      else	dprint (2, (debugfile, "pgp_copy_checksig: \"%s\" doesn't match regexp.\n",		    line));            if (strncmp (line, "[GNUPG:] ", 9) == 0)	continue;      fputs (line, fpout);      fputc ('\n', fpout);    }    FREE (&line);  }  else  {    dprint (2, (debugfile, "pgp_copy_checksig: No pattern.\n"));    mutt_copy_stream (fpin, fpout);    rv = 1;  }  return rv;}/*  * Copy a clearsigned message, and strip the signature and PGP's * dash-escaping. *  * XXX - charset handling: We assume that it is safe to do * character set decoding first, dash decoding second here, while * we do it the other way around in the main handler. *  * (Note that we aren't worse than Outlook &c in this, and also * note that we can successfully handle anything produced by any * existing versions of mutt.)  */static void pgp_copy_clearsigned (FILE *fpin, STATE *s, char *charset){  char buf[HUGE_STRING];  short complete, armor_header;    FGETCONV *fc;    rewind (fpin);    fc = fgetconv_open (fpin, charset, Charset, M_ICONV_HOOK_FROM);    for (complete = 1, armor_header = 1;       fgetconvs (buf, sizeof (buf), fc) != NULL;       complete = strchr (buf, '\n') != NULL)  {    if (!complete)    {      if (!armor_header)	state_puts (buf, s);      continue;    }    if (mutt_strcmp (buf, "-----BEGIN PGP SIGNATURE-----\n") == 0)      break;        if (armor_header)    {      char *p = mutt_skip_whitespace (buf);      if (*p == '\0') 	armor_header = 0;      continue;    }        if (s->prefix)       state_puts (s->prefix, s);        if (buf[0] == '-' && buf[1] == ' ')      state_puts (buf + 2, s);    else      state_puts (buf, s);  }    fgetconv_close (&fc);}/* Support for the Application/PGP Content Type. */int pgp_application_pgp_handler (BODY *m, STATE *s){  int could_not_decrypt = 0;  int needpass = -1, pgp_keyblock = 0;  int clearsign = 0, rv, rc;  int c = 1; /* silence GCC warning */  long start_pos = 0;  long bytes;  LOFF_T last_pos, offset;  char buf[HUGE_STRING];  char outfile[_POSIX_PATH_MAX];  char tmpfname[_POSIX_PATH_MAX];  FILE *pgpout = NULL, *pgpin = NULL, *pgperr = NULL;  FILE *tmpfp = NULL;  pid_t thepid;  short maybe_goodsig = 1;  short have_any_sigs = 0;  char body_charset[STRING];  mutt_get_body_charset (body_charset, sizeof (body_charset), m);  rc = 0;	/* silence false compiler warning if (s->flags & M_DISPLAY) */  fseeko (s->fpin, m->offset, 0);  last_pos = m->offset;    for (bytes = m->length; bytes > 0;)  {    if (fgets (buf, sizeof (buf), s->fpin) == NULL)      break;        offset = ftello (s->fpin);    bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf) */    last_pos = offset;        if (mutt_strncmp ("-----BEGIN PGP ", buf, 15) == 0)    {      clearsign = 0;      start_pos = last_pos;      if (mutt_strcmp ("MESSAGE-----\n", buf + 15) == 0)        needpass = 1;      else if (mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15) == 0)      {	clearsign = 1;        needpass = 0;      }      else if (!option (OPTDONTHANDLEPGPKEYS) &&	       mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15) == 0)      {        needpass = 0;        pgp_keyblock =1;      }       else      {	/* XXX - we may wish to recode here */	if (s->prefix)	  state_puts (s->prefix, s);	state_puts (buf, s);	continue;      }      have_any_sigs = have_any_sigs || (clearsign && (s->flags & M_VERIFY));      /* Copy PGP material to temporary file */      mutt_mktemp (tmpfname);      if ((tmpfp = safe_fopen (tmpfname, "w+")) == NULL)      {	mutt_perror (tmpfname);	return -1;      }            fputs (buf, tmpfp);      while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL)      {	offset = ftello (s->fpin);	bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf) */	last_pos = offset;		fputs (buf, tmpfp);	if ((needpass && mutt_strcmp ("-----END PGP MESSAGE-----\n", buf) == 0) ||	    (!needpass              && (mutt_strcmp ("-----END PGP SIGNATURE-----\n", buf) == 0                 || mutt_strcmp ("-----END PGP PUBLIC KEY BLOCK-----\n",buf) == 0)))	  break;      }      /* leave tmpfp open in case we still need it - but flush it! */      fflush (tmpfp);      /* Invoke PGP if needed */      if (!clearsign || (s->flags & M_VERIFY))      {	mutt_mktemp (outfile);	if ((pgpout = safe_fopen (outfile, "w+")) == NULL)	{	  mutt_perror (tmpfname);	  return -1;	}		if ((thepid = pgp_invoke_decode (&pgpin, NULL, &pgperr, -1,					 fileno (pgpout), -1, tmpfname,					 needpass)) == -1)	{	  safe_fclose (&pgpout);	  maybe_goodsig = 0;	  pgpin = NULL;	  pgperr = NULL;	  state_attach_puts (_("[-- Error: unable to create PGP subprocess! --]\n"), s);	}	else /* PGP started successfully */	{	  if (needpass)	  {	    if (!pgp_valid_passphrase ()) pgp_void_passphrase();            if (pgp_use_gpg_agent())              *PgpPass = 0;	    fprintf (pgpin, "%s\n", PgpPass);	  }	  	  safe_fclose (&pgpin);	  if (s->flags & M_DISPLAY)	  {	    crypt_current_time (s, "PGP");	    rc = pgp_copy_checksig (pgperr, s->fpout);	  }	  	  safe_fclose (&pgperr);	  rv = mutt_wait_filter (thepid);	  	  if (s->flags & M_DISPLAY)	  {	    if (rc == 0) have_any_sigs = 1;	    /*	     * Sig is bad if	     * gpg_good_sign-pattern did not match || pgp_decode_command returned not 0	     * Sig _is_ correct if	     *  gpg_good_sign="" && pgp_decode_command returned 0	     */	    if (rc == -1 || rv) maybe_goodsig = 0;	    	    state_attach_puts (_("[-- End of PGP output --]\n\n"), s);	  }	}	        /* treat empty result as sign of failure */	/* TODO: maybe on failure mutt should include the original undecoded text. */	if (pgpout)	{	  rewind (pgpout);	  c = fgetc (pgpout);	  ungetc (c, pgpout);	}        if (!clearsign && (!pgpout || c == EOF))	{	  could_not_decrypt = 1;	  pgp_void_passphrase ();	}		if (could_not_decrypt && !(s->flags & M_DISPLAY))	{          mutt_error _("Could not decrypt PGP message");	  mutt_sleep (1);	  rc = -1;	  goto out;        }      }            /*       * Now, copy cleartext to the screen.  NOTE - we expect that PGP       * outputs utf-8 cleartext.  This may not always be true, but it        * seems to be a reasonable guess.       */      if(s->flags & M_DISPLAY)      {	if (needpass)	  state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s);	else if (pgp_keyblock)	  state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"), s);	else	  state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"), s);      }      if (clearsign)      {	rewind (tmpfp);	if (tmpfp) 	  pgp_copy_clearsigned (tmpfp, s, body_charset);      }      else if (pgpout)      {	FGETCONV *fc;	int c;	rewind (pgpout);	state_set_prefix (s);	fc = fgetconv_open (pgpout, "utf-8", Charset, 0);	while ((c = fgetconv (fc)) != EOF)	  state_prefix_putc (c, s);	fgetconv_close (&fc);      }      if (s->flags & M_DISPLAY)      {	state_putc ('\n', s);	if (needpass)        {	  state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);	  if (could_not_decrypt)	    mutt_error _("Could not decrypt PGP message");	  else	    mutt_message _("PGP message successfully decrypted.");        }	else if (pgp_keyblock)	  state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s);	else	  state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s);      }    }    else    {      /* XXX - we may wish to recode here */      if (s->prefix)	state_puts (s->prefix, s);      state_puts (buf, s);    }  }  rc = 0;out:  m->goodsig = (maybe_goodsig && have_any_sigs);  if (tmpfp)  {    safe_fclose (&tmpfp);    mutt_unlink (tmpfname);  }  if (pgpout)  {    safe_fclose (&pgpout);    mutt_unlink (outfile);  }    if (needpass == -1)  {    state_attach_puts (_("[-- Error: could not find beginning of PGP message! --]\n\n"), s);    return -1;  }    return rc;}static int pgp_check_traditional_one_body (FILE *fp, BODY *b, int tagged_only){  char tempfile[_POSIX_PATH_MAX];  char buf[HUGE_STRING];  FILE *tfp;    short sgn = 0;  short enc = 0;  short key = 0;    if (b->type != TYPETEXT)    return 0;  if (tagged_only && !b->tagged)    return 0;  mutt_mktemp (tempfile);  if (mutt_decode_save_attachment (fp, b, tempfile, 0, 0) != 0)  {    unlink (tempfile);    return 0;  }    if ((tfp = fopen (tempfile, "r")) == NULL)  {    unlink (tempfile);    return 0;  }    while (fgets (buf, sizeof (buf), tfp))  {    if (mutt_strncmp ("-----BEGIN PGP ", buf, 15) == 0)    {      if (mutt_strcmp ("MESSAGE-----\n", buf + 15) == 0)	enc = 1;      else if (mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15) == 0)	sgn = 1;      else if (mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15) == 0)	key = 1;    }  }  safe_fclose (&tfp);  unlink (tempfile);  if (!enc && !sgn && !key)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -