mutt stable branch with some hacks
at master 358 lines 9.4 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 *signas, 168 const char *ids, 169 const char *format) 170{ 171 struct pgp_command_context cctx; 172 char cmd[HUGE_STRING]; 173 174 memset (&cctx, 0, sizeof (cctx)); 175 176 if (!format || !*format) 177 return (pid_t) -1; 178 179 cctx.need_passphrase = need_passphrase; 180 cctx.fname = fname; 181 cctx.sig_fname = sig_fname; 182 cctx.signas = signas; 183 cctx.ids = ids; 184 185 mutt_pgp_command (cmd, sizeof (cmd), &cctx, format); 186 187 return mutt_create_filter_fd (cmd, pgpin, pgpout, pgperr, 188 pgpinfd, pgpoutfd, pgperrfd); 189} 190 191 192/* 193 * The exported interface. 194 * 195 * This is historic and may be removed at some point. 196 * 197 */ 198 199 200pid_t pgp_invoke_decode (FILE **pgpin, FILE **pgpout, FILE **pgperr, 201 int pgpinfd, int pgpoutfd, int pgperrfd, 202 const char *fname, short need_passphrase) 203{ 204 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 205 need_passphrase, fname, NULL, PgpSignAs, NULL, 206 PgpDecodeCommand); 207} 208 209pid_t pgp_invoke_verify (FILE **pgpin, FILE **pgpout, FILE **pgperr, 210 int pgpinfd, int pgpoutfd, int pgperrfd, 211 const char *fname, const char *sig_fname) 212{ 213 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 214 0, fname, sig_fname, PgpSignAs, NULL, PgpVerifyCommand); 215} 216 217pid_t pgp_invoke_decrypt (FILE **pgpin, FILE **pgpout, FILE **pgperr, 218 int pgpinfd, int pgpoutfd, int pgperrfd, 219 const char *fname) 220{ 221 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 222 1, fname, NULL, PgpSignAs, NULL, PgpDecryptCommand); 223} 224 225pid_t pgp_invoke_sign (FILE **pgpin, FILE **pgpout, FILE **pgperr, 226 int pgpinfd, int pgpoutfd, int pgperrfd, 227 const char *fname) 228{ 229 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 230 1, fname, NULL, PgpSignAs, NULL, PgpSignCommand); 231} 232 233 234pid_t pgp_invoke_encrypt (FILE **pgpin, FILE **pgpout, FILE **pgperr, 235 int pgpinfd, int pgpoutfd, int pgperrfd, 236 const char *fname, const char *uids, int sign) 237{ 238 if (sign) 239 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 240 1, fname, NULL, PgpSignAs, uids, 241 PgpEncryptSignCommand); 242 else 243 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 244 0, fname, NULL, PgpSignAs, uids, 245 PgpEncryptOnlyCommand); 246} 247 248pid_t pgp_invoke_traditional (FILE **pgpin, FILE **pgpout, FILE **pgperr, 249 int pgpinfd, int pgpoutfd, int pgperrfd, 250 const char *fname, const char *uids, int flags) 251{ 252 if (flags & ENCRYPT) 253 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 254 flags & SIGN ? 1 : 0, fname, NULL, PgpSignAs, uids, 255 flags & SIGN ? PgpEncryptSignCommand : PgpEncryptOnlyCommand); 256 else 257 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 258 1, fname, NULL, PgpSignAs, NULL, 259 PgpClearSignCommand); 260} 261 262 263void pgp_invoke_import (const char *fname) 264{ 265 char _fname[_POSIX_PATH_MAX + SHORT_STRING]; 266 char cmd[HUGE_STRING]; 267 struct pgp_command_context cctx; 268 269 memset (&cctx, 0, sizeof (cctx)); 270 271 mutt_quote_filename (_fname, sizeof (_fname), fname); 272 cctx.fname = _fname; 273 cctx.signas = PgpSignAs; 274 275 mutt_pgp_command (cmd, sizeof (cmd), &cctx, PgpImportCommand); 276 mutt_system (cmd); 277} 278 279void pgp_invoke_getkeys (ADDRESS *addr) 280{ 281 char buff[LONG_STRING]; 282 char tmp[LONG_STRING]; 283 char cmd[HUGE_STRING]; 284 int devnull; 285 286 char *personal; 287 288 struct pgp_command_context cctx; 289 290 if (!PgpGetkeysCommand) return; 291 292 memset (&cctx, 0, sizeof (cctx)); 293 294 personal = addr->personal; 295 addr->personal = NULL; 296 297 *tmp = '\0'; 298 mutt_addrlist_to_local (addr); 299 rfc822_write_address_single (tmp, sizeof (tmp), addr, 0); 300 mutt_quote_filename (buff, sizeof (buff), tmp); 301 302 addr->personal = personal; 303 304 cctx.ids = buff; 305 306 mutt_pgp_command (cmd, sizeof (cmd), &cctx, PgpGetkeysCommand); 307 308 devnull = open ("/dev/null", O_RDWR); 309 310 if (!isendwin ()) mutt_message _("Fetching PGP key..."); 311 312 mutt_system (cmd); 313 314 if (!isendwin ()) mutt_clear_error (); 315 316 close (devnull); 317} 318 319pid_t pgp_invoke_export (FILE **pgpin, FILE **pgpout, FILE **pgperr, 320 int pgpinfd, int pgpoutfd, int pgperrfd, 321 const char *uids) 322{ 323 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 324 0, NULL, NULL, PgpSignAs, uids, 325 PgpExportCommand); 326} 327 328pid_t pgp_invoke_verify_key (FILE **pgpin, FILE **pgpout, FILE **pgperr, 329 int pgpinfd, int pgpoutfd, int pgperrfd, 330 const char *uids) 331{ 332 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 333 0, NULL, NULL, PgpSignAs, uids, 334 PgpVerifyKeyCommand); 335} 336 337pid_t pgp_invoke_list_keys (FILE **pgpin, FILE **pgpout, FILE **pgperr, 338 int pgpinfd, int pgpoutfd, int pgperrfd, 339 pgp_ring_t keyring, LIST *hints) 340{ 341 char uids[HUGE_STRING]; 342 char tmpuids[HUGE_STRING]; 343 char quoted[HUGE_STRING]; 344 345 *uids = '\0'; 346 347 for (; hints; hints = hints->next) 348 { 349 mutt_quote_filename (quoted, sizeof (quoted), (char *) hints->data); 350 snprintf (tmpuids, sizeof (tmpuids), "%s %s", uids, quoted); 351 strcpy (uids, tmpuids); /* __STRCPY_CHECKED__ */ 352 } 353 354 return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, 355 0, NULL, NULL, PgpSignAs, uids, 356 keyring == PGP_SECRING ? PgpListSecringCommand : 357 PgpListPubringCommand); 358}