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