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