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