📄 pgp.c
字号:
t->disposition = DISPINLINE; mutt_generate_boundary (&t->parameter); mutt_set_parameter ("protocol", "application/pgp-signature", &t->parameter); mutt_set_parameter ("micalg", pgp_micalg (sigfile), &t->parameter); t->parts = a; a = t; t->parts->next = mutt_new_body (); t = t->parts->next; t->type = TYPEAPPLICATION; t->subtype = safe_strdup ("pgp-signature"); t->filename = safe_strdup (sigfile); t->use_disp = 0; t->disposition = DISPINLINE; t->encoding = ENC7BIT; t->unlink = 1; /* ok to remove this file after sending. */ return (a);}static short is_numerical_keyid (const char *s){ /* or should we require the "0x"? */ if (strncmp (s, "0x", 2) == 0) s += 2; if (strlen (s) % 8) return 0; while (*s) if (strchr ("0123456789ABCDEFabcdef", *s++) == NULL) return 0; return 1;}/* This routine attempts to find the keyids of the recipients of a message. * It returns NULL if any of the keys can not be found. */char *pgp_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc){ char *keyID, *keylist = NULL, *t; size_t keylist_size = 0; size_t keylist_used = 0; ADDRESS *tmp = NULL, *addr = NULL; ADDRESS **last = &tmp; ADDRESS *p, *q; int i; pgp_key_t k_info = NULL, key = NULL; const char *fqdn = mutt_fqdn (1); for (i = 0; i < 3; i++) { switch (i) { case 0: p = to; break; case 1: p = cc; break; case 2: p = bcc; break; default: abort (); } *last = rfc822_cpy_adr (p); while (*last) last = &((*last)->next); } if (fqdn) rfc822_qualify (tmp, fqdn); tmp = mutt_remove_duplicates (tmp); for (p = tmp; p ; p = p->next) { char buf[LONG_STRING]; q = p; k_info = NULL; if ((keyID = mutt_crypt_hook (p)) != NULL) { int r; snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, p->mailbox); if ((r = mutt_yesorno (buf, M_YES)) == M_YES) { if (is_numerical_keyid (keyID)) { if (strncmp (keyID, "0x", 2) == 0) keyID += 2; goto bypass_selection; /* you don't see this. */ } /* check for e-mail address */ if ((t = strchr (keyID, '@')) && (addr = rfc822_parse_adrlist (NULL, keyID))) { if (fqdn) rfc822_qualify (addr, fqdn); q = addr; } else k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING); } else if (r == -1) { FREE (&keylist); rfc822_free_address (&tmp); rfc822_free_address (&addr); return NULL; } } if (k_info == NULL) pgp_invoke_getkeys (q); if (k_info == NULL && (k_info = pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) { snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox); if ((key = pgp_ask_for_key (buf, q->mailbox, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) { FREE (&keylist); rfc822_free_address (&tmp); rfc822_free_address (&addr); return NULL; } } else key = k_info; keyID = pgp_keyid (key); bypass_selection: keylist_size += mutt_strlen (keyID) + 4; safe_realloc (&keylist, keylist_size); sprintf (keylist + keylist_used, "%s0x%s", keylist_used ? " " : "", /* __SPRINTF_CHECKED__ */ keyID); keylist_used = mutt_strlen (keylist); pgp_free_key (&key); rfc822_free_address (&addr); } rfc822_free_address (&tmp); return (keylist);}/* Warning: "a" is no longer freed in this routine, you need * to free it later. This is necessary for $fcc_attach. */BODY *pgp_encrypt_message (BODY *a, char *keylist, int sign){ char buf[LONG_STRING]; char tempfile[_POSIX_PATH_MAX], pgperrfile[_POSIX_PATH_MAX]; char pgpinfile[_POSIX_PATH_MAX]; FILE *pgpin, *pgperr, *fpout, *fptmp; BODY *t; int err = 0; int empty = 0; pid_t thepid; mutt_mktemp (tempfile); if ((fpout = safe_fopen (tempfile, "w+")) == NULL) { mutt_perror (tempfile); return (NULL); } mutt_mktemp (pgperrfile); if ((pgperr = safe_fopen (pgperrfile, "w+")) == NULL) { mutt_perror (pgperrfile); unlink(tempfile); fclose(fpout); return NULL; } unlink (pgperrfile); mutt_mktemp(pgpinfile); if((fptmp = safe_fopen(pgpinfile, "w")) == NULL) { mutt_perror(pgpinfile); unlink(tempfile); fclose(fpout); fclose(pgperr); return NULL; } if (sign) convert_to_7bit (a); mutt_write_mime_header (a, fptmp); fputc ('\n', fptmp); mutt_write_mime_body (a, fptmp); fclose(fptmp); if ((thepid = pgp_invoke_encrypt (&pgpin, NULL, NULL, -1, fileno (fpout), fileno (pgperr), pgpinfile, keylist, sign)) == -1) { fclose (pgperr); unlink(pgpinfile); return (NULL); } if (sign) { if (!pgp_use_gpg_agent()) fputs (PgpPass, pgpin); fputc ('\n', pgpin); } fclose(pgpin); if(mutt_wait_filter (thepid) && option(OPTPGPCHECKEXIT)) empty=1; unlink(pgpinfile); fflush (fpout); rewind (fpout); if(!empty) empty = (fgetc (fpout) == EOF); fclose (fpout); fflush (pgperr); rewind (pgperr); while (fgets (buf, sizeof (buf) - 1, pgperr) != NULL) { err = 1; fputs (buf, stdout); } fclose (pgperr); /* pause if there is any error output from PGP */ if (err) mutt_any_key_to_continue (NULL); if (empty) { /* fatal error while trying to encrypt message */ if (sign) pgp_void_passphrase (); /* just in case */ unlink (tempfile); return (NULL); } t = mutt_new_body (); t->type = TYPEMULTIPART; t->subtype = safe_strdup ("encrypted"); t->encoding = ENC7BIT; t->use_disp = 0; t->disposition = DISPINLINE; mutt_generate_boundary(&t->parameter); mutt_set_parameter("protocol", "application/pgp-encrypted", &t->parameter); t->parts = mutt_new_body (); t->parts->type = TYPEAPPLICATION; t->parts->subtype = safe_strdup ("pgp-encrypted"); t->parts->encoding = ENC7BIT; t->parts->next = mutt_new_body (); t->parts->next->type = TYPEAPPLICATION; t->parts->next->subtype = safe_strdup ("octet-stream"); t->parts->next->encoding = ENC7BIT; t->parts->next->filename = safe_strdup (tempfile); t->parts->next->use_disp = 1; t->parts->next->disposition = DISPINLINE; t->parts->next->unlink = 1; /* delete after sending the message */ t->parts->next->d_filename = safe_strdup ("msg.asc"); /* non pgp/mime can save */ return (t);}BODY *pgp_traditional_encryptsign (BODY *a, int flags, char *keylist){ BODY *b; char pgpoutfile[_POSIX_PATH_MAX]; char pgperrfile[_POSIX_PATH_MAX]; char pgpinfile[_POSIX_PATH_MAX]; char body_charset[STRING]; char *from_charset; const char *send_charset; FILE *pgpout = NULL, *pgperr = NULL, *pgpin = NULL; FILE *fp; int empty = 0; int err; char buff[STRING]; pid_t thepid; if (a->type != TYPETEXT) return NULL; if (ascii_strcasecmp (a->subtype, "plain")) return NULL; if ((fp = fopen (a->filename, "r")) == NULL) { mutt_perror (a->filename); return NULL; } mutt_mktemp (pgpinfile); if ((pgpin = safe_fopen (pgpinfile, "w")) == NULL) { mutt_perror (pgpinfile); fclose (fp); return NULL; } /* The following code is really correct: If noconv is set, * a's charset parameter contains the on-disk character set, and * we have to convert from that to utf-8. If noconv is not set, * we have to convert from $charset to utf-8. */ mutt_get_body_charset (body_charset, sizeof (body_charset), a); if (a->noconv) from_charset = body_charset; else from_charset = Charset; if (!mutt_is_us_ascii (body_charset)) { int c; FGETCONV *fc; if (flags & ENCRYPT) send_charset = "us-ascii"; else send_charset = "utf-8"; fc = fgetconv_open (fp, from_charset, "utf-8", M_ICONV_HOOK_FROM); while ((c = fgetconv (fc)) != EOF) fputc (c, pgpin); fgetconv_close (&fc); } else { send_charset = "us-ascii"; mutt_copy_stream (fp, pgpin); } safe_fclose (&fp); fclose (pgpin); mutt_mktemp (pgpoutfile); mutt_mktemp (pgperrfile); if ((pgpout = safe_fopen (pgpoutfile, "w+")) == NULL || (pgperr = safe_fopen (pgperrfile, "w+")) == NULL) { mutt_perror (pgpout ? pgperrfile : pgpoutfile); unlink (pgpinfile); if (pgpout) { fclose (pgpout); unlink (pgpoutfile); } return NULL; } unlink (pgperrfile); if ((thepid = pgp_invoke_traditional (&pgpin, NULL, NULL, -1, fileno (pgpout), fileno (pgperr), pgpinfile, keylist, flags)) == -1) { mutt_perror _("Can't invoke PGP"); fclose (pgpout); fclose (pgperr); mutt_unlink (pgpinfile); unlink (pgpoutfile); return NULL; } if (pgp_use_gpg_agent()) *PgpPass = 0; if (flags & SIGN) fprintf (pgpin, "%s\n", PgpPass); fclose (pgpin); if(mutt_wait_filter (thepid) && option(OPTPGPCHECKEXIT)) empty=1; mutt_unlink (pgpinfile); fflush (pgpout); fflush (pgperr); rewind (pgpout); rewind (pgperr); if(!empty) empty = (fgetc (pgpout) == EOF); fclose (pgpout); err = 0; while (fgets (buff, sizeof (buff), pgperr)) { err = 1; fputs (buff, stdout); } fclose (pgperr); if (err) mutt_any_key_to_continue (NULL); if (empty) { if (flags & SIGN) pgp_void_passphrase (); /* just in case */ unlink (pgpoutfile); return NULL; } b = mutt_new_body (); b->encoding = ENC7BIT; b->type = TYPETEXT; b->subtype = safe_strdup ("plain"); mutt_set_parameter ("x-action", flags & ENCRYPT ? "pgp-encrypted" : "pgp-signed", &b->parameter); mutt_set_parameter ("charset", send_charset, &b->parameter); b->filename = safe_strdup (pgpoutfile); #if 0 /* The following is intended to give a clue to some completely brain-dead * "mail environments" which are typically used by large corporations. */ b->d_filename = safe_strdup ("msg.pgp"); b->use_disp = 1;#endif b->disposition = DISPINLINE; b->unlink = 1; b->noconv = 1; b->use_disp = 0; if (!(flags & ENCRYPT)) b->encoding = a->encoding; return b;}int pgp_send_menu (HEADER *msg, int *redraw){ pgp_key_t p; char input_signas[SHORT_STRING]; char prompt[LONG_STRING]; if (!(WithCrypto & APPLICATION_PGP)) return msg->security; /* If autoinline and no crypto options set, then set inline. */ if (option (OPTPGPAUTOINLINE) && !((msg->security & APPLICATION_PGP) && (msg->security & (SIGN|ENCRYPT)))) msg->security |= INLINE; snprintf (prompt, sizeof (prompt), _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, %s, or (c)lear? "), (msg->security & INLINE) ? _("PGP/M(i)ME") : _("(i)nline")); switch (mutt_multi_choice (prompt, _("esabifc"))) { case 1: /* (e)ncrypt */ msg->security |= ENCRYPT; msg->security &= ~SIGN; break; case 2: /* (s)ign */ msg->security |= SIGN; msg->security &= ~ENCRYPT; break; case 3: /* sign (a)s */ unset_option(OPTPGPCHECKTRUST); if ((p = pgp_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN, PGP_PUBRING))) { snprintf (input_signas, sizeof (input_signas), "0x%s", pgp_keyid (p)); mutt_str_replace (&PgpSignAs, input_signas); pgp_free_key (&p); msg->security |= SIGN; crypt_pgp_void_passphrase (); /* probably need a different passphrase */ }#if 0 else { msg->security &= ~SIGN; }#endif *redraw = REDRAW_FULL; break; case 4: /* (b)oth */ msg->security |= (ENCRYPT | SIGN); break; case 5: /* (i)nline */ if ((msg->security & (ENCRYPT | SIGN))) msg->security ^= INLINE; else msg->security &= ~INLINE; break; case 6: /* (f)orget it */ case 7: /* (c)lear */ msg->security = 0; break; } if (msg->security) { if (! (msg->security & (ENCRYPT | SIGN))) msg->security = 0; else msg->security |= APPLICATION_PGP; } return (msg->security);}#endif /* CRYPT_BACKEND_CLASSIC_PGP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -