mutt stable branch with some hacks
at jcs 375 lines 9.6 kB view raw
1/* 2 * Copyright (C) 1997-2003 Thomas Roessler <roessler@does-not-exist.org> 3 * 4 * This program is free software; you can redistribute it 5 * and/or modify it under the terms of the GNU General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later 8 * version. 9 * 10 * This program is distributed in the hope that it will be 11 * useful, but WITHOUT ANY WARRANTY; without even the implied 12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 13 * PURPOSE. See the GNU General Public License for more 14 * details. 15 * 16 * You should have received a copy of the GNU General Public 17 * License along with this program; if not, write to the Free 18 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA. 20 */ 21 22/* This file contains the new pgp invocation code. Note that this 23 * is almost entirely format based. 24 */ 25 26#if HAVE_CONFIG_H 27# include "config.h" 28#endif 29 30#include <sys/types.h> 31#include <sys/stat.h> 32 33#include <stdio.h> 34#include <stdlib.h> 35#include <string.h> 36#include <unistd.h> 37#include <fcntl.h> 38#include <time.h> 39 40#include "mutt.h" 41#include "mutt_curses.h" 42#include "mutt_idna.h" 43#include "pgp.h" 44#include "rfc822.h" 45 46/* 47 * The actual command line formatter. 48 */ 49 50struct pgp_command_context { 51 short need_passphrase; /* %p */ 52 const char *fname; /* %f */ 53 const char *sig_fname; /* %s */ 54 const char *signas; /* %a */ 55 const char *ids; /* %r */ 56}; 57 58 59const char *_mutt_fmt_pgp_command (char *dest, 60 size_t destlen, 61 size_t col, 62 int cols, 63 char op, 64 const char *src, 65 const char *prefix, 66 const char *ifstring, 67 const char *elsestring, 68 unsigned long data, 69 format_flag flags) 70{ 71 char fmt[16]; 72 struct pgp_command_context *cctx = (struct pgp_command_context *) data; 73 int optional = (flags & MUTT_FORMAT_OPTIONAL); 74 75 switch (op) 76 { 77 case 'r': 78 { 79 if (!optional) 80 { 81 snprintf (fmt, sizeof (fmt), "%%%ss", prefix); 82 snprintf (dest, destlen, fmt, NONULL (cctx->ids)); 83 } 84 else if (!cctx->ids) 85 optional = 0; 86 break; 87 } 88 89 case 'a': 90 { 91 if (!optional) 92 { 93 snprintf (fmt, sizeof (fmt), "%%%ss", prefix); 94 snprintf (dest, destlen, fmt, NONULL (cctx->signas)); 95 } 96 else if (!cctx->signas) 97 optional = 0; 98 break; 99 } 100 101 case 's': 102 { 103 if (!optional) 104 { 105 snprintf (fmt, sizeof (fmt), "%%%ss", prefix); 106 snprintf (dest, destlen, fmt, NONULL (cctx->sig_fname)); 107 } 108 else if (!cctx->sig_fname) 109 optional = 0; 110 break; 111 } 112 113 case 'f': 114 { 115 if (!optional) 116 { 117 snprintf (fmt, sizeof (fmt), "%%%ss", prefix); 118 snprintf (dest, destlen, fmt, NONULL (cctx->fname)); 119 } 120 else if (!cctx->fname) 121 optional = 0; 122 break; 123 } 124 125 case 'p': 126 { 127 if (!optional) 128 { 129 snprintf (fmt, sizeof (fmt), "%%%ss", prefix); 130 snprintf (dest, destlen, fmt, cctx->need_passphrase ? "PGPPASSFD=0" : ""); 131 } 132 else if (!cctx->need_passphrase || pgp_use_gpg_agent()) 133 optional = 0; 134 break; 135 } 136 default: 137 { 138 *dest = '\0'; 139 break; 140 } 141 } 142 143 if (optional) 144 mutt_FormatString (dest, destlen, col, cols, ifstring, _mutt_fmt_pgp_command, data, 0); 145 else if (flags & MUTT_FORMAT_OPTIONAL) 146 mutt_FormatString (dest, destlen, col, cols, elsestring, _mutt_fmt_pgp_command, data, 0); 147 148 return (src); 149} 150 151void mutt_pgp_command (char *d, size_t dlen, struct pgp_command_context *cctx, const char *fmt) 152{ 153 mutt_FormatString (d, dlen, 0, MuttIndexWindow->cols, NONULL (fmt), _mutt_fmt_pgp_command, (unsigned long) cctx, 0); 154 dprint (2, (debugfile, "mutt_pgp_command: %s\n", d)); 155} 156 157/* 158 * Glue. 159 */ 160 161 162static pid_t pgp_invoke (FILE **pgpin, FILE **pgpout, FILE **pgperr, 163 int pgpinfd, int pgpoutfd, int pgperrfd, 164 short need_passphrase, 165 const char *fname, 166 const char *sig_fname, 167 const char *ids, 168 const char *format) 169{ 170 struct pgp_command_context cctx; 171 char cmd[HUGE_STRING]; 172 173 memset (&cctx, 0, sizeof (cctx)); 174 175 if (!format || !*format) 176 return (pid_t) -1; 177 178 cctx.need_passphrase = need_passphrase; 179 cctx.fname = fname; 180 cctx.sig_fname = sig_fname; 181 if (PgpSignAs) 182 cctx.signas = PgpSignAs; 183 else 184 cctx.signas = PgpDefaultKey; 185 cctx.ids = ids; 186 187 mutt_pgp_command (cmd, sizeof (cmd), &cctx, format); 188 189 return mutt_create_filter_fd (cmd, pgpin, pgpout, pgperr, 190 pgpinfd, pgpoutfd, pgperrfd); 191} 192 193 194/* 195 * The exported interface. 196 * 197 * This is historic and may be removed at some point. 198 * 199 */ 200 201pid_t pgp_invoke_decode (FILE **pgpin, FILE **pgpout, FILE **pgperr, 202 int pgpinfd, int pgpoutfd, int pgperrfd, 203 const char *fname, short need_passphrase) 204{ 205 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 206 need_passphrase, fname, NULL, NULL, 207 PgpDecodeCommand); 208} 209 210pid_t pgp_invoke_verify (FILE **pgpin, FILE **pgpout, FILE **pgperr, 211 int pgpinfd, int pgpoutfd, int pgperrfd, 212 const char *fname, const char *sig_fname) 213{ 214 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 215 0, fname, sig_fname, NULL, PgpVerifyCommand); 216} 217 218pid_t pgp_invoke_decrypt (FILE **pgpin, FILE **pgpout, FILE **pgperr, 219 int pgpinfd, int pgpoutfd, int pgperrfd, 220 const char *fname) 221{ 222 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 223 1, fname, NULL, NULL, PgpDecryptCommand); 224} 225 226pid_t pgp_invoke_sign (FILE **pgpin, FILE **pgpout, FILE **pgperr, 227 int pgpinfd, int pgpoutfd, int pgperrfd, 228 const char *fname) 229{ 230 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 231 1, fname, NULL, NULL, PgpSignCommand); 232} 233 234 235pid_t pgp_invoke_encrypt (FILE **pgpin, FILE **pgpout, FILE **pgperr, 236 int pgpinfd, int pgpoutfd, int pgperrfd, 237 const char *fname, const char *uids, int sign) 238{ 239 if (sign) 240 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 241 1, fname, NULL, uids, 242 PgpEncryptSignCommand); 243 else 244 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 245 0, fname, NULL, uids, 246 PgpEncryptOnlyCommand); 247} 248 249pid_t pgp_invoke_traditional (FILE **pgpin, FILE **pgpout, FILE **pgperr, 250 int pgpinfd, int pgpoutfd, int pgperrfd, 251 const char *fname, const char *uids, int flags) 252{ 253 if (flags & ENCRYPT) 254 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 255 flags & SIGN ? 1 : 0, fname, NULL, uids, 256 flags & SIGN ? PgpEncryptSignCommand : PgpEncryptOnlyCommand); 257 else 258 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 259 1, fname, NULL, NULL, 260 PgpClearSignCommand); 261} 262 263 264void pgp_invoke_import (const char *fname) 265{ 266 BUFFER *fnamebuf = NULL; 267 char cmd[HUGE_STRING]; 268 struct pgp_command_context cctx; 269 270 fnamebuf = mutt_buffer_pool_get (); 271 272 memset (&cctx, 0, sizeof (cctx)); 273 274 mutt_buffer_quote_filename (fnamebuf, fname); 275 cctx.fname = mutt_b2s (fnamebuf); 276 if (PgpSignAs) 277 cctx.signas = PgpSignAs; 278 else 279 cctx.signas = PgpDefaultKey; 280 281 mutt_pgp_command (cmd, sizeof (cmd), &cctx, PgpImportCommand); 282 mutt_system (cmd); 283 284 mutt_buffer_pool_release (&fnamebuf); 285} 286 287void pgp_invoke_getkeys (ADDRESS *addr) 288{ 289 BUFFER *buff = NULL; 290 char tmp[LONG_STRING]; 291 char cmd[HUGE_STRING]; 292 int devnull; 293 294 char *personal; 295 296 struct pgp_command_context cctx; 297 298 if (!PgpGetkeysCommand) return; 299 300 buff = mutt_buffer_pool_get (); 301 memset (&cctx, 0, sizeof (cctx)); 302 303 personal = addr->personal; 304 addr->personal = NULL; 305 306 *tmp = '\0'; 307 mutt_addrlist_to_local (addr); 308 rfc822_write_address_single (tmp, sizeof (tmp), addr, 0); 309 mutt_buffer_quote_filename (buff, tmp); 310 311 addr->personal = personal; 312 313 cctx.ids = mutt_b2s (buff); 314 315 mutt_pgp_command (cmd, sizeof (cmd), &cctx, PgpGetkeysCommand); 316 317 devnull = open ("/dev/null", O_RDWR); 318 319 if (!isendwin ()) mutt_message _("Fetching PGP key..."); 320 321 mutt_system (cmd); 322 323 if (!isendwin ()) mutt_clear_error (); 324 325 close (devnull); 326 327 mutt_buffer_pool_release (&buff); 328} 329 330pid_t pgp_invoke_export (FILE **pgpin, FILE **pgpout, FILE **pgperr, 331 int pgpinfd, int pgpoutfd, int pgperrfd, 332 const char *uids) 333{ 334 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 335 0, NULL, NULL, uids, 336 PgpExportCommand); 337} 338 339pid_t pgp_invoke_verify_key (FILE **pgpin, FILE **pgpout, FILE **pgperr, 340 int pgpinfd, int pgpoutfd, int pgperrfd, 341 const char *uids) 342{ 343 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 344 0, NULL, NULL, uids, 345 PgpVerifyKeyCommand); 346} 347 348pid_t pgp_invoke_list_keys (FILE **pgpin, FILE **pgpout, FILE **pgperr, 349 int pgpinfd, int pgpoutfd, int pgperrfd, 350 pgp_ring_t keyring, LIST *hints) 351{ 352 BUFFER *uids; 353 BUFFER *quoted; 354 pid_t rc; 355 356 uids = mutt_buffer_pool_get (); 357 quoted = mutt_buffer_pool_get (); 358 359 for (; hints; hints = hints->next) 360 { 361 mutt_buffer_quote_filename (quoted, (char *) hints->data); 362 mutt_buffer_addstr (uids, mutt_b2s (quoted)); 363 if (hints->next) 364 mutt_buffer_addch (uids, ' '); 365 } 366 367 rc = pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 368 0, NULL, NULL, mutt_b2s (uids), 369 keyring == PGP_SECRING ? PgpListSecringCommand : 370 PgpListPubringCommand); 371 372 mutt_buffer_pool_release (&uids); 373 mutt_buffer_pool_release (&quoted); 374 return rc; 375}