📄 smime.c
字号:
snprintf (signedfile, sizeof (signedfile), "%s.sig", tempfile); /* decode to a tempfile, saving the original destination */ fp = s->fpout; if ((s->fpout = safe_fopen (signedfile, "w")) == NULL) { mutt_perror (signedfile); return -1; } /* decoding the attachment changes the size and offset, so save a copy * of the "real" values now, and restore them after processing */ tmplength = sigbdy->length; tmpoffset = sigbdy->offset; /* if we are decoding binary bodies, we don't want to prefix each * line with the prefix or else the data will get corrupted. */ savePrefix = s->prefix; s->prefix = NULL; mutt_decode_attachment (sigbdy, s); sigbdy->length = ftello (s->fpout); sigbdy->offset = 0; fclose (s->fpout); /* restore final destination and substitute the tempfile for input */ s->fpout = fp; fp = s->fpin; s->fpin = fopen (signedfile, "r"); /* restore the prefix */ s->prefix = savePrefix; sigbdy->type = origType; mutt_mktemp (smimeerrfile); if (!(smimeerr = safe_fopen (smimeerrfile, "w+"))) { mutt_perror (smimeerrfile); mutt_unlink (signedfile); return -1; } crypt_current_time (s, "OpenSSL"); if ((thepid = smime_invoke_verify (NULL, &smimeout, NULL, -1, -1, fileno (smimeerr), tempfile, signedfile, 0)) != -1) { fflush (smimeout); fclose (smimeout); if (mutt_wait_filter (thepid)) badsig = -1; else { char *line = NULL; int lineno = 0; size_t linelen; fflush (smimeerr); rewind (smimeerr); line = mutt_read_line (line, &linelen, smimeerr, &lineno); if (linelen && !ascii_strcasecmp (line, "verification successful")) badsig = 0; FREE (&line); } } fflush (smimeerr); rewind (smimeerr); mutt_copy_stream (smimeerr, s->fpout); fclose (smimeerr); state_attach_puts (_("[-- End of OpenSSL output --]\n\n"), s); mutt_unlink (signedfile); mutt_unlink (smimeerrfile); sigbdy->length = tmplength; sigbdy->offset = tmpoffset; /* restore the original source stream */ fclose (s->fpin); s->fpin = fp; return badsig;}/* This handles application/pkcs7-mime which can either be a signed or an encrypted message.*/static BODY *smime_handle_entity (BODY *m, STATE *s, FILE *outFile){ int len=0; int c; long last_pos; char buf[HUGE_STRING]; char outfile[_POSIX_PATH_MAX], errfile[_POSIX_PATH_MAX]; char tmpfname[_POSIX_PATH_MAX]; char tmptmpfname[_POSIX_PATH_MAX]; FILE *smimeout = NULL, *smimein=NULL, *smimeerr=NULL; FILE *tmpfp=NULL, *tmpfp_buffer=NULL, *fpout=NULL; struct stat info; BODY *p=NULL; pid_t thepid=-1; unsigned int type = mutt_is_application_smime (m); if (!(type & APPLICATION_SMIME)) return NULL; mutt_mktemp (outfile); if ((smimeout = safe_fopen (outfile, "w+")) == NULL) { mutt_perror (outfile); return NULL; } mutt_mktemp (errfile); if ((smimeerr = safe_fopen (errfile, "w+")) == NULL) { mutt_perror (errfile); fclose (smimeout); smimeout = NULL; return NULL; } mutt_unlink (errfile); mutt_mktemp (tmpfname); if ((tmpfp = safe_fopen (tmpfname, "w+")) == NULL) { mutt_perror (tmpfname); fclose (smimeout); smimeout = NULL; fclose (smimeerr); smimeerr = NULL; return NULL; } fseeko (s->fpin, m->offset, 0); last_pos = m->offset; mutt_copy_bytes (s->fpin, tmpfp, m->length); fflush (tmpfp); fclose (tmpfp); if ((type & ENCRYPT) && (thepid = smime_invoke_decrypt (&smimein, NULL, NULL, -1, fileno (smimeout), fileno (smimeerr), tmpfname)) == -1) { fclose (smimeout); smimeout = NULL; mutt_unlink (tmpfname); if (s->flags & M_DISPLAY) state_attach_puts (_("[-- Error: unable to create OpenSSL subprocess! --]\n"), s); return NULL; } else if ((type & SIGNOPAQUE) && (thepid = smime_invoke_verify (&smimein, NULL, NULL, -1, fileno (smimeout), fileno (smimeerr), NULL, tmpfname, SIGNOPAQUE)) == -1) { fclose (smimeout); smimeout = NULL; mutt_unlink (tmpfname); if (s->flags & M_DISPLAY) state_attach_puts (_("[-- Error: unable to create OpenSSL subprocess! --]\n"), s); return NULL; } if (type & ENCRYPT) { if (!smime_valid_passphrase ()) smime_void_passphrase (); fputs (SmimePass, smimein); fputc ('\n', smimein); } fclose (smimein); mutt_wait_filter (thepid); mutt_unlink (tmpfname); if (s->flags & M_DISPLAY) { rewind (smimeerr); if ((c = fgetc (smimeerr)) != EOF) { ungetc (c, smimeerr); crypt_current_time (s, "OpenSSL"); mutt_copy_stream (smimeerr, s->fpout); state_attach_puts (_("[-- End of OpenSSL output --]\n\n"), s); } if (type & ENCRYPT) state_attach_puts (_("[-- The following data is S/MIME" " encrypted --]\n"), s); else state_attach_puts (_("[-- The following data is S/MIME signed --]\n"), s); } if (smimeout) { fflush (smimeout); rewind (smimeout); if (outFile) fpout = outFile; else { mutt_mktemp (tmptmpfname); if ((fpout = safe_fopen (tmptmpfname, "w+")) == NULL) { mutt_perror(tmptmpfname); fclose (smimeout); smimeout = NULL; return NULL; } } while (fgets (buf, sizeof (buf) - 1, smimeout) != NULL) { len = mutt_strlen (buf); if (len > 1 && buf[len - 2] == '\r') { buf[len-2] = '\n'; buf[len-1] = '\0'; } fputs (buf, fpout); } fflush (fpout); rewind (fpout); if ((p = mutt_read_mime_header (fpout, 0)) != NULL) { fstat (fileno (fpout), &info); p->length = info.st_size - p->offset; mutt_parse_part (fpout, p); if (s->fpout) { rewind (fpout); tmpfp_buffer = s->fpin; s->fpin = fpout; mutt_body_handler (p, s); s->fpin = tmpfp_buffer; } } fclose (smimeout); smimeout = NULL; mutt_unlink (outfile); if (!outFile) { fclose (fpout); mutt_unlink (tmptmpfname); } fpout = NULL; } if (s->flags & M_DISPLAY) { if (type & ENCRYPT) state_attach_puts (_("\n[-- End of S/MIME encrypted data. --]\n"), s); else state_attach_puts (_("\n[-- End of S/MIME signed data. --]\n"), s); } if (type & SIGNOPAQUE) { char *line = NULL; int lineno = 0; size_t linelen; rewind (smimeerr); line = mutt_read_line (line, &linelen, smimeerr, &lineno); if (linelen && !ascii_strcasecmp (line, "verification successful")) m->goodsig = 1; FREE (&line); } else { m->goodsig = p->goodsig; m->badsig = p->badsig; } fclose (smimeerr); return (p);}int smime_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur){ char tempfile[_POSIX_PATH_MAX]; STATE s; long tmpoffset = b->offset; size_t tmplength = b->length; int origType = b->type; FILE *tmpfp=NULL; int rv = 0; if (!mutt_is_application_smime (b)) return -1; if (b->parts) return -1; memset (&s, 0, sizeof (s)); s.fpin = fpin; fseeko (s.fpin, b->offset, 0); mutt_mktemp (tempfile); if ((tmpfp = safe_fopen (tempfile, "w+")) == NULL) { 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); s.fpin = tmpfp; s.fpout = 0; mutt_mktemp (tempfile); if ((*fpout = safe_fopen (tempfile, "w+")) == NULL) { mutt_perror (tempfile); rv = -1; goto bail; } mutt_unlink (tempfile); if (!(*cur = smime_handle_entity (b, &s, *fpout))) { rv = -1; goto bail; } (*cur)->goodsig = b->goodsig; (*cur)->badsig = b->badsig;bail: b->type = origType; b->length = tmplength; b->offset = tmpoffset; safe_fclose (&tmpfp); if (*fpout) rewind (*fpout); return rv;}int smime_application_smime_handler (BODY *m, STATE *s){ return smime_handle_entity (m, s, NULL) ? 0 : -1;}int smime_send_menu (HEADER *msg, int *redraw){ char *p; if (!(WithCrypto & APPLICATION_SMIME)) return msg->security; switch (mutt_multi_choice (_("S/MIME (e)ncrypt, (s)ign, encrypt (w)ith, sign (a)s, (b)oth, or (c)lear? "), _("eswabfc"))) { case 1: /* (e)ncrypt */ msg->security |= ENCRYPT; msg->security &= ~SIGN; break; case 3: /* encrypt (w)ith */ { int choice = 0; msg->security |= ENCRYPT; do { /* I use "dra" because "123" is recognized anyway */ switch (mutt_multi_choice (_("Choose algorithm family:" " 1: DES, 2: RC2, 3: AES," " or (c)lear? "), _("drac"))) { case 1: switch (choice = mutt_multi_choice (_("1: DES, 2: Triple-DES "), _("dt"))) { case 1: mutt_str_replace (&SmimeCryptAlg, "des"); break; case 2: mutt_str_replace (&SmimeCryptAlg, "des3"); break; } break; case 2: switch (choice = mutt_multi_choice (_("1: RC2-40, 2: RC2-64, 3: RC2-128 "), _("468"))) { case 1: mutt_str_replace (&SmimeCryptAlg, "rc2-40"); break; case 2: mutt_str_replace (&SmimeCryptAlg, "rc2-64"); break; case 3: mutt_str_replace (&SmimeCryptAlg, "rc2-128"); break; } break; case 3: switch (choice = mutt_multi_choice (_("1: AES128, 2: AES192, 3: AES256 "), _("895"))) { case 1: mutt_str_replace (&SmimeCryptAlg, "aes128"); break; case 2: mutt_str_replace (&SmimeCryptAlg, "aes192"); break; case 3: mutt_str_replace (&SmimeCryptAlg, "aes256"); break; } break; case 4: /* (c)lear */ FREE (&SmimeCryptAlg); /* fallback */ case -1: /* Ctrl-G or Enter */ choice = 0; break; } } while (choice == -1); } break; case 2: /* (s)ign */ if(!SmimeDefaultKey) mutt_message _("Can't sign: No key specified. Use Sign As."); else { msg->security |= SIGN; msg->security &= ~ENCRYPT; } break; case 4: /* sign (a)s */ if ((p = smime_ask_for_key (_("Sign as: "), NULL, 0))) { mutt_str_replace (&SmimeDefaultKey, p); msg->security |= SIGN; /* probably need a different passphrase */ crypt_smime_void_passphrase (); }#if 0 else msg->security &= ~SIGN;#endif *redraw = REDRAW_FULL; break; case 5: /* (b)oth */ msg->security |= (ENCRYPT | SIGN); break; case 6: /* (f)orget it */ case 7: /* (c)lear */ msg->security = 0; break; } if (msg->security && msg->security != APPLICATION_SMIME) msg->security |= APPLICATION_SMIME; else msg->security = 0; return (msg->security);}#endif /* CRYPT_BACKEND_CLASSIC_SMIME */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -