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