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