Nico Golde:
[apps/madmutt.git] / pgpinvoke.c
1 /*
2  * Copyright notice from original mutt:
3  * Copyright (C) 1997-2000 Thomas Roessler <roessler@does-not-exist.org>
4  *
5  * This file is part of mutt-ng, see http://www.muttng.org/.
6  * It's licensed under the GNU General Public License,
7  * please see the file GPL in the top level source directory.
8  */
9
10 /* This file contains the new pgp invocation code.  Note that this
11  * is almost entirely format based.
12  */
13
14 #if HAVE_CONFIG_H
15 # include "config.h"
16 #endif
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <time.h>
27
28 #include "mutt.h"
29 #include "mutt_curses.h"
30 #include "mutt_idna.h"
31 #include "pgp.h"
32 #include "rfc822.h"
33
34 #include "lib/mem.h"
35 #include "lib/intl.h"
36 #include "lib/str.h"
37
38 /*
39  * The actual command line formatter.
40  */
41
42 struct pgp_command_context {
43   short need_passphrase;        /* %p */
44   const char *fname;            /* %f */
45   const char *sig_fname;        /* %s */
46   const char *signas;           /* %a */
47   const char *ids;              /* %r */
48 };
49
50
51 const char *_mutt_fmt_pgp_command (char *dest,
52                                    size_t destlen,
53                                    char op,
54                                    const char *src,
55                                    const char *prefix,
56                                    const char *ifstring,
57                                    const char *elsestring,
58                                    unsigned long data, format_flag flags)
59 {
60   char fmt[16];
61   struct pgp_command_context *cctx = (struct pgp_command_context *) data;
62   int optional = (flags & M_FORMAT_OPTIONAL);
63
64   switch (op) {
65   case 'r':
66     {
67       if (!optional) {
68         snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
69         snprintf (dest, destlen, fmt, NONULL (cctx->ids));
70       }
71       else if (!cctx->ids)
72         optional = 0;
73       break;
74     }
75
76   case 'a':
77     {
78       if (!optional) {
79         snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
80         snprintf (dest, destlen, fmt, NONULL (cctx->signas));
81       }
82       else if (!cctx->signas)
83         optional = 0;
84       break;
85     }
86
87   case 's':
88     {
89       if (!optional) {
90         snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
91         snprintf (dest, destlen, fmt, NONULL (cctx->sig_fname));
92       }
93       else if (!cctx->sig_fname)
94         optional = 0;
95       break;
96     }
97
98   case 'f':
99     {
100       if (!optional) {
101         snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
102         snprintf (dest, destlen, fmt, NONULL (cctx->fname));
103       }
104       else if (!cctx->fname)
105         optional = 0;
106       break;
107     }
108
109   case 'p':
110     {
111       if (!optional) {
112         snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
113         snprintf (dest, destlen, fmt,
114                   cctx->need_passphrase ? "PGPPASSFD=0" : "");
115       }
116       else if (!cctx->need_passphrase || pgp_use_gpg_agent ())
117         optional = 0;
118       break;
119     }
120   default:
121     {
122       *dest = '\0';
123       break;
124     }
125   }
126
127   if (optional)
128     mutt_FormatString (dest, destlen, ifstring, _mutt_fmt_pgp_command, data,
129                        0);
130   else if (flags & M_FORMAT_OPTIONAL)
131     mutt_FormatString (dest, destlen, elsestring, _mutt_fmt_pgp_command, data,
132                        0);
133
134   return (src);
135 }
136
137 void mutt_pgp_command (char *d, size_t dlen, struct pgp_command_context *cctx,
138                        const char *fmt)
139 {
140   mutt_FormatString (d, dlen, NONULL (fmt), _mutt_fmt_pgp_command,
141                      (unsigned long) cctx, 0);
142   dprint (2, (debugfile, "mutt_pgp_command: %s\n", d));
143 }
144
145 /*
146  * Glue.
147  */
148
149
150 static pid_t pgp_invoke (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
151                          int pgpinfd, int pgpoutfd, int pgperrfd,
152                          short need_passphrase,
153                          const char *fname,
154                          const char *sig_fname,
155                          const char *signas,
156                          const char *ids, const char *format)
157 {
158   struct pgp_command_context cctx;
159   char cmd[HUGE_STRING];
160
161   memset (&cctx, 0, sizeof (cctx));
162
163   if (!format || !*format)
164     return (pid_t) - 1;
165
166   cctx.need_passphrase = need_passphrase;
167   cctx.fname = fname;
168   cctx.sig_fname = sig_fname;
169   cctx.signas = signas;
170   cctx.ids = ids;
171
172   mutt_pgp_command (cmd, sizeof (cmd), &cctx, format);
173
174   return mutt_create_filter_fd (cmd, pgpin, pgpout, pgperr,
175                                 pgpinfd, pgpoutfd, pgperrfd);
176 }
177
178
179 /*
180  * The exported interface.
181  * 
182  * This is historic and may be removed at some point.
183  *
184  */
185
186
187 pid_t pgp_invoke_decode (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
188                          int pgpinfd, int pgpoutfd, int pgperrfd,
189                          const char *fname, short need_passphrase)
190 {
191   return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
192                      need_passphrase, fname, NULL, NULL, NULL,
193                      PgpDecodeCommand);
194 }
195
196 pid_t pgp_invoke_verify (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
197                          int pgpinfd, int pgpoutfd, int pgperrfd,
198                          const char *fname, const char *sig_fname)
199 {
200   return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
201                      0, fname, sig_fname, NULL, NULL, PgpVerifyCommand);
202 }
203
204 pid_t pgp_invoke_decrypt (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
205                           int pgpinfd, int pgpoutfd, int pgperrfd,
206                           const char *fname)
207 {
208   return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
209                      1, fname, NULL, NULL, NULL, PgpDecryptCommand);
210 }
211
212 pid_t pgp_invoke_sign (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
213                        int pgpinfd, int pgpoutfd, int pgperrfd,
214                        const char *fname)
215 {
216   return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
217                      1, fname, NULL, PgpSignAs, NULL, PgpSignCommand);
218 }
219
220
221 pid_t pgp_invoke_encrypt (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
222                           int pgpinfd, int pgpoutfd, int pgperrfd,
223                           const char *fname, const char *uids, int sign)
224 {
225   if (sign)
226     return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
227                        1, fname, NULL, PgpSignAs, uids,
228                        PgpEncryptSignCommand);
229   else
230     return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
231                        0, fname, NULL, NULL, uids, PgpEncryptOnlyCommand);
232 }
233
234 pid_t pgp_invoke_traditional (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
235                               int pgpinfd, int pgpoutfd, int pgperrfd,
236                               const char *fname, const char *uids, int flags)
237 {
238   if (flags & ENCRYPT)
239     return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
240                        flags & SIGN ? 1 : 0, fname, NULL, PgpSignAs, uids,
241                        flags & SIGN ? PgpEncryptSignCommand :
242                        PgpEncryptOnlyCommand);
243   else
244     return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
245                        1, fname, NULL, PgpSignAs, NULL, PgpClearSignCommand);
246 }
247
248
249 void pgp_invoke_import (const char *fname)
250 {
251   char _fname[_POSIX_PATH_MAX + SHORT_STRING];
252   char cmd[HUGE_STRING];
253   struct pgp_command_context cctx;
254
255   memset (&cctx, 0, sizeof (cctx));
256
257   mutt_quote_filename (_fname, sizeof (_fname), fname);
258   cctx.fname = _fname;
259
260   mutt_pgp_command (cmd, sizeof (cmd), &cctx, PgpImportCommand);
261   mutt_system (cmd);
262 }
263
264 void pgp_invoke_getkeys (ADDRESS * addr)
265 {
266   char buff[LONG_STRING];
267   char tmp[LONG_STRING];
268   char cmd[HUGE_STRING];
269   int devnull;
270
271   char *personal;
272
273   struct pgp_command_context cctx;
274
275   if (!PgpGetkeysCommand)
276     return;
277
278   memset (&cctx, 0, sizeof (cctx));
279
280   personal = addr->personal;
281   addr->personal = NULL;
282
283   *tmp = '\0';
284   mutt_addrlist_to_local (addr);
285   rfc822_write_address_single (tmp, sizeof (tmp), addr, 0);
286   mutt_quote_filename (buff, sizeof (buff), tmp);
287
288   addr->personal = personal;
289
290   cctx.ids = buff;
291
292   mutt_pgp_command (cmd, sizeof (cmd), &cctx, PgpGetkeysCommand);
293
294   devnull = open ("/dev/null", O_RDWR);
295
296   if (!isendwin ())
297     mutt_message _("Fetching PGP key...");
298
299   mutt_system (cmd);
300
301   if (!isendwin ())
302     mutt_clear_error ();
303
304   close (devnull);
305 }
306
307 pid_t pgp_invoke_export (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
308                          int pgpinfd, int pgpoutfd, int pgperrfd,
309                          const char *uids)
310 {
311   return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
312                      0, NULL, NULL, NULL, uids, PgpExportCommand);
313 }
314
315 pid_t pgp_invoke_verify_key (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
316                              int pgpinfd, int pgpoutfd, int pgperrfd,
317                              const char *uids)
318 {
319   return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
320                      0, NULL, NULL, NULL, uids, PgpVerifyKeyCommand);
321 }
322
323 pid_t pgp_invoke_list_keys (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
324                             int pgpinfd, int pgpoutfd, int pgperrfd,
325                             pgp_ring_t keyring, LIST * hints)
326 {
327   char uids[HUGE_STRING];
328   char tmpuids[HUGE_STRING];
329   char quoted[HUGE_STRING];
330
331   *uids = '\0';
332
333   for (; hints; hints = hints->next) {
334     mutt_quote_filename (quoted, sizeof (quoted), (char *) hints->data);
335     snprintf (tmpuids, sizeof (tmpuids), "%s %s", uids, quoted);
336     strcpy (uids, tmpuids);     /* __STRCPY_CHECKED__ */
337   }
338
339   return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
340                      0, NULL, NULL, NULL, uids,
341                      keyring == PGP_SECRING ? PgpListSecringCommand :
342                      PgpListPubringCommand);
343 }