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

📄 crypt-gpgme.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 5 页
字号:
      return NULL;  }  mutt_need_hard_redraw ();  /* Read the output from GPGME, and make sure to change CRLF to LF,     otherwise read_mime_header has a hard time parsing the message.  */  if (data_object_to_stream (plaintext, fpout))    {      gpgme_data_release (plaintext);      gpgme_release (ctx);      return NULL;    }  gpgme_data_release (plaintext);  a->is_signed_data = 0;  if (sig_stat)    {      int res, idx;      int anybad = 0;            if (maybe_signed)        a->is_signed_data = 1;      if(r_is_signed)        *r_is_signed = -1; /* A signature exists. */      if ((s->flags & M_DISPLAY))        state_attach_puts (_("[-- Begin signature "                             "information --]\n"), s);      for(idx = 0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++)        {          if (res == 1)            anybad = 1;          else if (res == 2)            anywarn = 1;        }      if (!anybad && idx && r_is_signed && *r_is_signed)        *r_is_signed = anywarn? 2:1; /* Good signature. */            if ((s->flags & M_DISPLAY))        state_attach_puts (_("[-- End signature "                             "information --]\n\n"), s);    }  gpgme_release (ctx); ctx = NULL;  fflush (fpout);  rewind (fpout);  tattach = mutt_read_mime_header (fpout, 0);  if (tattach)    {      /*       * Need to set the length of this body part.       */      fstat (fileno (fpout), &info);      tattach->length = info.st_size - tattach->offset;            tattach->warnsig = anywarn;      /* See if we need to recurse on this MIME part.  */      mutt_parse_part (fpout, tattach);    }  return tattach;}/* Decrypt a PGP/MIME message in FPIN and B and return a new body and   the stream in CUR and FPOUT.  Returns 0 on success. */int pgp_gpgme_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur){  char tempfile[_POSIX_PATH_MAX];  STATE s;  BODY *first_part = b;  int is_signed;    first_part->goodsig = 0;  first_part->warnsig = 0;  if(!mutt_is_multipart_encrypted(b))    return -1;  if(!b->parts || !b->parts->next)    return -1;    b = b->parts->next;    memset (&s, 0, sizeof (s));  s.fpin = fpin;  mutt_mktemp (tempfile);  if (!(*fpout = safe_fopen (tempfile, "w+")))  {    mutt_perror (tempfile);    return -1;  }  unlink (tempfile);  *cur = decrypt_part (b, &s, *fpout, 0, &is_signed);  rewind (*fpout);  if (is_signed > 0)    first_part->goodsig = 1;    return *cur? 0:-1;}/* Decrypt a S/MIME message in FPIN and B and return a new body and   the stream in CUR and FPOUT.  Returns 0 on success. */int smime_gpgme_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur){  char tempfile[_POSIX_PATH_MAX];  STATE s;  FILE *tmpfp=NULL;  int is_signed;  LOFF_T saved_b_offset;  size_t saved_b_length;  int saved_b_type;  if (!mutt_is_application_smime (b))    return -1;  if (b->parts)    return -1;    /* Decode the body - we need to pass binary CMS to the     backend.  The backend allows for Base64 encoded data but it does     not allow for QP which I have seen in some messages.  So better     do it here. */  saved_b_type = b->type;  saved_b_offset = b->offset;  saved_b_length = b->length;  memset (&s, 0, sizeof (s));  s.fpin = fpin;  fseeko (s.fpin, b->offset, 0);   mutt_mktemp (tempfile);  if (!(tmpfp = safe_fopen (tempfile, "w+")))    {      mutt_perror (tempfile);      return -1;    }  mutt_unlink (tempfile);  s.fpout = tmpfp;  mutt_decode_attachment (b, &s);  fflush (tmpfp);  b->length = ftello (s.fpout);  b->offset = 0;  rewind (tmpfp);  memset (&s, 0, sizeof (s));  s.fpin = tmpfp;  s.fpout = 0;  mutt_mktemp (tempfile);  if (!(*fpout = safe_fopen (tempfile, "w+")))    {      mutt_perror (tempfile);      return -1;    }  mutt_unlink (tempfile);  *cur = decrypt_part (b, &s, *fpout, 1, &is_signed);  if (*cur)    (*cur)->goodsig = is_signed > 0;  b->type = saved_b_type;  b->length = saved_b_length;  b->offset = saved_b_offset;  fclose (tmpfp);  rewind (*fpout);  if (*cur && !is_signed && !(*cur)->parts && mutt_is_application_smime (*cur))    {      /* Assume that this is a opaque signed s/mime message.  This is         an ugly way of doing it but we have anyway a problem with         arbitrary encoded S/MIME messages: Only the outer part may be         encrypted.  The entire mime parsing should be revamped,         probably by keeping the temportary files so that we don't         need to decrypt them all the time.  Inner parts of an         encrypted part can then pint into this file and tehre won't         never be a need to decrypt again.  This needs a partial         rewrite of the MIME engine. */      BODY *bb = *cur;      BODY *tmp_b;      saved_b_type = bb->type;      saved_b_offset = bb->offset;      saved_b_length = bb->length;      memset (&s, 0, sizeof (s));      s.fpin = *fpout;      fseeko (s.fpin, bb->offset, 0);       mutt_mktemp (tempfile);      if (!(tmpfp = safe_fopen (tempfile, "w+")))        {          mutt_perror (tempfile);          return -1;        }      mutt_unlink (tempfile);      s.fpout = tmpfp;      mutt_decode_attachment (bb, &s);      fflush (tmpfp);      bb->length = ftello (s.fpout);      bb->offset = 0;      rewind (tmpfp);      fclose (*fpout);       memset (&s, 0, sizeof (s));      s.fpin = tmpfp;      s.fpout = 0;      mutt_mktemp (tempfile);      if (!(*fpout = safe_fopen (tempfile, "w+")))        {          mutt_perror (tempfile);          return -1;        }      mutt_unlink (tempfile);      tmp_b = decrypt_part (bb, &s, *fpout, 1, &is_signed);      if (tmp_b)        tmp_b->goodsig = is_signed > 0;      bb->type = saved_b_type;      bb->length = saved_b_length;      bb->offset = saved_b_offset;      fclose (tmpfp);      rewind (*fpout);      mutt_free_body (cur);      *cur = tmp_b;    }  return *cur? 0:-1;}/*  * Implementation of `pgp_check_traditional'. */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;    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))    {      if (!mutt_strcmp ("MESSAGE-----\n", buf + 15))	enc = 1;      else if (!mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15))	sgn = 1;    }  }  safe_fclose (&tfp);  unlink (tempfile);  if (!enc && !sgn)    return 0;  /* fix the content type */    mutt_set_parameter ("format", "fixed", &b->parameter);  mutt_set_parameter ("x-action", enc ? "pgp-encrypted" : "pgp-signed",                      &b->parameter);    return 1;}int pgp_gpgme_check_traditional (FILE *fp, BODY *b, int tagged_only){  int rv = 0;  int r;  for (; b; b = b->next)  {    if (is_multipart (b))      rv = (pgp_gpgme_check_traditional (fp, b->parts, tagged_only) || rv);    else if (b->type == TYPETEXT)    {      if ((r = mutt_is_application_pgp (b)))	rv = (rv || r);      else	rv = (pgp_check_traditional_one_body (fp, b, tagged_only) || rv);    }  }  return rv;}/*  * Implementation of `application_handler'. *//*   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 & Cie in this, and also  note that we can successfully handle anything produced by any  existing versions of mutt.)  */static void copy_clearsigned (gpgme_data_t data, STATE *s, char *charset){  char buf[HUGE_STRING];  short complete, armor_header;  FGETCONV *fc;  char *fname;  FILE *fp;  fname = data_object_to_tempfile (data, &fp);  if (!fname)    return;  unlink (fname);  FREE (&fname);    fc = fgetconv_open (fp, 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"))      break;        if (armor_header)    {      if (buf[0] == '\n') 	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);  fclose (fp);}/* Support for classic_application/pgp */int pgp_gpgme_application_handler (BODY *m, STATE *s){  int needpass = -1, pgp_keyblock = 0;  int clearsign = 0;  long start_pos = 0;  long bytes;  LOFF_T last_pos, offset;  char buf[HUGE_STRING];  FILE *pgpout = NULL;  gpgme_error_t err = 0;  gpgme_data_t armored_data = NULL;  short maybe_goodsig = 1;  short have_any_sigs = 0;  char body_charset[STRING];  /* Only used for clearsigned messages. */  dprint (2, (debugfile, "Entering pgp_application_pgp handler\n"));  /* For clearsigned messages we won't be able to get a character set     but we know that this may only be text thus we assume Latin-1     here. */  if (!mutt_get_body_charset (body_charset, sizeof (body_charset), m))    strfcpy (body_charset, "iso-8859-1", sizeof body_charset);  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))        {          clearsign = 0;          start_pos = last_pos;                    if (!mutt_strcmp ("MESSAGE-----\n", buf + 15))            needpass = 1;          else if (!mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15))            {              clearsign = 1;              needpass = 0;            }          else if (!option (OPTDONTHANDLEPGPKEYS) &&                   !mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15))            {              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 an data container */          armored_data = create_gpgme_data ();          gpgme_data_write (armored_data, buf, strlen (buf));          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;                            gpgme_data_write (armored_data, buf, strlen (buf));                            if ((needpass                   && !mutt_strcmp ("-----END PGP MESSAGE-----\n", buf))                   || (!needpass                       && (!mutt_strcmp ("-----END PGP SIGNATURE-----\n", buf)                          || !mutt_strcmp (                                "-----END PGP PUBLIC KEY BLOCK-----\n",buf))))                break;            }                    /* Invoke PGP if needed */          if (!clearsign || (s->flags & M_VERIFY))            {              unsigned int sig_stat = 0;              gpgme_data_t plaintext;              gpgme_ctx_t ctx;              plaintext = create_gpgme_data ();              ctx = create_gpgme_context (0);              if (clearsign)                err = gpgme_op_verify (ctx, armored_data, NULL, plaintext);              else                {                  err = gpgme_op_decrypt_verify (ctx, armored_data, plaintext);                  if (gpg_err_code (err) == GPG_ERR_NO_DATA)                    {                      /* Decrypt verify can't handle signed only messages. */		      err = (gpgme_data_seek (armored_data, 0, SEEK_SET) == -1)			? gpgme_error_from_errno (errno) : 0;                      /* Must release plaintext so that we supply an                         uninitialized object. */                      gpgme_data_release (plaintext);                      plaintext = create_gpgme_data ();                      err = gpgme_op_verify (ctx, armored_data,                                             NULL, plaintext);                    }                }              if (err)                {                  char errbuf[200];                                    snprintf (errbuf, sizeof(errbuf)-1,                             _("Error: decryption/verification failed: %s\n"),                            gpgme_strerror (err));                  state_attach_puts (errbuf, s);                }              else                { /* Decryption/Verification succeeded */                  char *tmpfname;		  {		    /* Check wether signatures have been verified.  */

⌨️ 快捷键说明

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