pgpinvoke.c 8.73 KB
Newer Older
Thomas Roessler's avatar
Thomas Roessler committed
1
/*
2
 * Copyright (C) 1997-2000 Thomas Roessler <roessler@guug.de>
Thomas Roessler's avatar
Thomas Roessler committed
3
 * 
4 5 6 7 8
 *     This program is free software; you can redistribute it
 *     and/or modify it under the terms of the GNU General Public
 *     License as published by the Free Software Foundation; either
 *     version 2 of the License, or (at your option) any later
 *     version.
Thomas Roessler's avatar
Thomas Roessler committed
9
 * 
10 11 12 13 14
 *     This program is distributed in the hope that it will be
 *     useful, but WITHOUT ANY WARRANTY; without even the implied
 *     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 *     PURPOSE.  See the GNU General Public License for more
 *     details.
Thomas Roessler's avatar
Thomas Roessler committed
15
 * 
16 17
 *     You should have received a copy of the GNU General Public
 *     License along with this program; if not, write to the Free
18 19
 *     Software Foundation, Inc., 59 Temple Place - Suite 330,
 *     Boston, MA  02111, USA.
Thomas Roessler's avatar
Thomas Roessler committed
20 21
 */ 

22 23 24 25
/* This file contains the new pgp invocation code.  Note that this
 * is almost entirely format based.
 */

26 27 28
#include <sys/types.h>
#include <sys/stat.h>

Thomas Roessler's avatar
Thomas Roessler committed
29 30 31 32
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
33
#include <fcntl.h>
Thomas Roessler's avatar
Thomas Roessler committed
34 35 36
#include <time.h>

#include "mutt.h"
37
#include "mutt_curses.h"
Thomas Roessler's avatar
Thomas Roessler committed
38
#include "pgp.h"
39
#include "rfc822.h"
Thomas Roessler's avatar
Thomas Roessler committed
40

41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
/*
 * The actual command line formatter.
 */

struct pgp_command_context {
  short need_passphrase;	/* %p */
  const char *fname;		/* %f */
  const char *sig_fname;	/* %s */
  const char *signas;		/* %a */
  const char *ids;		/* %r */
};


const char *_mutt_fmt_pgp_command (char *dest,
				   size_t destlen,
				   char op,
				   const char *src,
				   const char *prefix,
				   const char *ifstring,
				   const char *elsestring,
				   unsigned long data,
				   format_flag flags)
63
{
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
  char fmt[16];
  struct pgp_command_context *cctx = (struct pgp_command_context *) data;
  int optional = (flags & M_FORMAT_OPTIONAL);
  
  switch (op)
  {
    case 'r':
    {
      if (!optional)
      {
	snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
	snprintf (dest, destlen, fmt, NONULL (cctx->ids));
      }
      else if (!cctx->ids)
	optional = 0;
      break;
    }
    
    case 'a':
    {
      if (!optional)
      {
	snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
	snprintf (dest, destlen, fmt, NONULL (cctx->signas));
      }
      else if (!cctx->signas)
	optional = 0;
      break;
    }
    
    case 's':
    {
      if (!optional)
      {
	snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
	snprintf (dest, destlen, fmt, NONULL (cctx->sig_fname));
      }
      else if (!cctx->sig_fname)
	optional = 0;
      break;
    }
    
    case 'f':
    {
      if (!optional)
      {
	snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
	snprintf (dest, destlen, fmt, NONULL (cctx->fname));
      }
      else if (!cctx->fname)
	optional = 0;
      break;
    }
    
    case 'p':
    {
      if (!optional)
      {
	snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
	snprintf (dest, destlen, fmt, cctx->need_passphrase ? "PGPPASSFD=0" : "");
      }
      else if (!cctx->need_passphrase)
	optional = 0;
      break;
    }
Thomas Roessler's avatar
Thomas Roessler committed
129 130 131 132 133
    default:
    {
      *dest = '\0';
      break;
    }
134
  }
Thomas Roessler's avatar
Thomas Roessler committed
135

136
  if (optional)
Thomas Roessler's avatar
Thomas Roessler committed
137
    mutt_FormatString (dest, destlen, ifstring, _mutt_fmt_pgp_command, data, 0);
138
  else if (flags & M_FORMAT_OPTIONAL)
Thomas Roessler's avatar
Thomas Roessler committed
139 140
    mutt_FormatString (dest, destlen, elsestring, _mutt_fmt_pgp_command, data, 0);

141
  return (src);
142 143
}

144
void mutt_pgp_command (char *d, size_t dlen, struct pgp_command_context *cctx, const char *fmt)
145
{
146 147
  mutt_FormatString (d, dlen, NONULL (fmt), _mutt_fmt_pgp_command, (unsigned long) cctx, 0);
  dprint (2, (debugfile, "mutt_pgp_command: %s\n", d));
148 149
}

150 151 152 153 154 155 156 157 158 159 160 161 162
/*
 * Glue.
 */


static pid_t pgp_invoke (FILE **pgpin, FILE **pgpout, FILE **pgperr,
			 int pgpinfd, int pgpoutfd, int pgperrfd,
			 short need_passphrase,
			 const char *fname,
			 const char *sig_fname,
			 const char *signas,
			 const char *ids,
			 const char *format)
163
{
164
  struct pgp_command_context cctx;
165
  char cmd[HUGE_STRING];
166 167
  
  memset (&cctx, 0, sizeof (cctx));
168 169 170

  if (!format || !*format)
    return (pid_t) -1;
171 172 173 174 175 176 177 178 179 180
  
  cctx.need_passphrase = need_passphrase;
  cctx.fname	       = fname;
  cctx.sig_fname       = sig_fname;
  cctx.signas	       = signas;
  cctx.ids	       = ids;
  
  mutt_pgp_command (cmd, sizeof (cmd), &cctx, format);
  
  return mutt_create_filter_fd (cmd, pgpin, pgpout, pgperr,
181
			       pgpinfd, pgpoutfd, pgperrfd);
Thomas Roessler's avatar
Thomas Roessler committed
182 183 184
}


185 186
/*
 * The exported interface.
187
 * 
188 189 190
 * This is historic and may be removed at some point.
 *
 */
191

Thomas Roessler's avatar
Thomas Roessler committed
192

193 194 195
pid_t pgp_invoke_decode (FILE **pgpin, FILE **pgpout, FILE **pgperr,
			 int pgpinfd, int pgpoutfd, int pgperrfd, 
			 const char *fname, short need_passphrase)
Thomas Roessler's avatar
Thomas Roessler committed
196
{
197 198 199
  return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
		     need_passphrase, fname, NULL, NULL, NULL, 
		     PgpDecodeCommand);
200
}
Thomas Roessler's avatar
Thomas Roessler committed
201

202
pid_t pgp_invoke_verify (FILE **pgpin, FILE **pgpout, FILE **pgperr,
203
			 int pgpinfd, int pgpoutfd, int pgperrfd, 
204
			 const char *fname, const char *sig_fname)
205
{
206 207
  return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
		     0, fname, sig_fname, NULL, NULL, PgpVerifyCommand);
Thomas Roessler's avatar
Thomas Roessler committed
208 209
}

210 211 212
pid_t pgp_invoke_decrypt (FILE **pgpin, FILE **pgpout, FILE **pgperr,
			  int pgpinfd, int pgpoutfd, int pgperrfd, 
			  const char *fname)
Thomas Roessler's avatar
Thomas Roessler committed
213
{
214 215
  return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
		     1, fname, NULL, NULL, NULL, PgpDecryptCommand);
216 217
}

218 219 220
pid_t pgp_invoke_sign (FILE **pgpin, FILE **pgpout, FILE **pgperr,
		       int pgpinfd, int pgpoutfd, int pgperrfd, 
		       const char *fname)
221
{
222 223
  return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
		     1, fname, NULL, PgpSignAs, NULL, PgpSignCommand);
224 225 226
}


227 228 229
pid_t pgp_invoke_encrypt (FILE **pgpin, FILE **pgpout, FILE **pgperr,
			  int pgpinfd, int pgpoutfd, int pgperrfd,
			  const char *fname, const char *uids, int sign)
230
{
231 232 233 234 235 236 237 238
  if (sign)
    return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
		       1, fname, NULL, PgpSignAs, uids, 
		       PgpEncryptSignCommand);
  else
    return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
		       0, fname, NULL, NULL, uids, 
		       PgpEncryptOnlyCommand);
239
}
Thomas Roessler's avatar
Thomas Roessler committed
240

241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
pid_t pgp_invoke_traditional (FILE **pgpin, FILE **pgpout, FILE **pgperr,
			      int pgpinfd, int pgpoutfd, int pgperrfd,
			      const char *fname, const char *uids, int flags)
{
  if (flags & PGPENCRYPT)
    return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
		       flags & PGPSIGN ? 1 : 0, fname, NULL, PgpSignAs, uids, 
		       flags & PGPSIGN ? PgpEncryptSignCommand : PgpEncryptOnlyCommand);
  else
    return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
		       1, fname, NULL, PgpSignAs, NULL,
		       PgpClearSignCommand);
}


256
void pgp_invoke_import (const char *fname)
257
{
258
  char _fname[_POSIX_PATH_MAX + SHORT_STRING];
259
  char cmd[HUGE_STRING];
260 261 262 263
  struct pgp_command_context cctx;
  
  memset (&cctx, 0, sizeof (cctx));
  
264
  mutt_quote_filename (_fname, sizeof (_fname), fname);
265 266 267 268
  cctx.fname = _fname;
  
  mutt_pgp_command (cmd, sizeof (cmd), &cctx, PgpImportCommand);
  mutt_system (cmd);
269 270
}

271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
void pgp_invoke_getkeys (ADDRESS *addr)
{
  char buff[LONG_STRING];
  char tmp[LONG_STRING];
  char cmd[HUGE_STRING];
  int devnull;

  char *personal;
  
  struct pgp_command_context cctx;

  if (!PgpGetkeysCommand) return;
  
  memset (&cctx, 0, sizeof (cctx));

  personal = addr->personal;
  addr->personal = NULL;
  
  *tmp = '\0';
  rfc822_write_address_single (tmp, sizeof (tmp), addr);
  mutt_quote_filename (buff, sizeof (buff), tmp);

  addr->personal = personal;
  
  cctx.ids = buff;
  
  mutt_pgp_command (cmd, sizeof (cmd), &cctx, PgpGetkeysCommand);

  devnull = open ("/dev/null", O_RDWR);

  if (!isendwin ()) mutt_message  _("Fetching PGP key...");

  mutt_system (cmd);

  if (!isendwin ()) mutt_clear_error ();
306 307

  close (devnull);
308 309
}

310 311 312
pid_t pgp_invoke_export (FILE **pgpin, FILE **pgpout, FILE **pgperr,
			 int pgpinfd, int pgpoutfd, int pgperrfd, 
			 const char *uids)
313
{
314 315 316
  return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
		     0, NULL, NULL, NULL, uids,
		     PgpExportCommand);
317
}
318

319 320 321
pid_t pgp_invoke_verify_key (FILE **pgpin, FILE **pgpout, FILE **pgperr,
			     int pgpinfd, int pgpoutfd, int pgperrfd, 
			     const char *uids)
322
{
323 324 325
  return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
		     0, NULL, NULL, NULL, uids,
		     PgpVerifyKeyCommand);
Thomas Roessler's avatar
Thomas Roessler committed
326 327
}

328 329 330
pid_t pgp_invoke_list_keys (FILE **pgpin, FILE **pgpout, FILE **pgperr,
			    int pgpinfd, int pgpoutfd, int pgperrfd, 
			    pgp_ring_t keyring, LIST *hints)
Thomas Roessler's avatar
Thomas Roessler committed
331
{
332 333
  char uids[HUGE_STRING];
  char tmpuids[HUGE_STRING];
334

335 336 337
  *uids = '\0';
  
  for (; hints; hints = hints->next)
Thomas Roessler's avatar
Thomas Roessler committed
338
  {
339 340
    snprintf (tmpuids, sizeof (tmpuids), "%s %s", uids, (char *) hints->data);
    strcpy (uids, tmpuids);
Thomas Roessler's avatar
Thomas Roessler committed
341
  }
342

343 344 345 346
  return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
		     0, NULL, NULL, NULL, uids,
		     keyring == PGP_SECRING ? PgpListSecringCommand :
		     PgpListPubringCommand);
Thomas Roessler's avatar
Thomas Roessler committed
347
}