Andreas Krennmair:
[apps/madmutt.git] / pgpinvoke.c
1 /*
2  * Copyright (C) 1997-2000 Thomas Roessler <roessler@does-not-exist.org>
3  * 
4  *     This program is free software; you can redistribute it
5  *     and/or modify it under the terms of the GNU General Public
6  *     License as published by the Free Software Foundation; either
7  *     version 2 of the License, or (at your option) any later
8  *     version.
9  * 
10  *     This program is distributed in the hope that it will be
11  *     useful, but WITHOUT ANY WARRANTY; without even the implied
12  *     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13  *     PURPOSE.  See the GNU General Public License for more
14  *     details.
15  * 
16  *     You should have received a copy of the GNU General Public
17  *     License along with this program; if not, write to the Free
18  *     Software Foundation, Inc., 59 Temple Place - Suite 330,
19  *     Boston, MA  02111, USA.
20  */
21
22 /* This file contains the new pgp invocation code.  Note that this
23  * is almost entirely format based.
24  */
25
26 #if HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <sys/types.h>
31 #include <sys/stat.h>
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <time.h>
39
40 #include "mutt.h"
41 #include "mutt_curses.h"
42 #include "mutt_idna.h"
43 #include "pgp.h"
44 #include "rfc822.h"
45
46 /*
47  * The actual command line formatter.
48  */
49
50 struct pgp_command_context {
51   short need_passphrase;        /* %p */
52   const char *fname;            /* %f */
53   const char *sig_fname;        /* %s */
54   const char *signas;           /* %a */
55   const char *ids;              /* %r */
56 };
57
58
59 const char *_mutt_fmt_pgp_command (char *dest,
60                                    size_t destlen,
61                                    char op,
62                                    const char *src,
63                                    const char *prefix,
64                                    const char *ifstring,
65                                    const char *elsestring,
66                                    unsigned long data, format_flag flags)
67 {
68   char fmt[16];
69   struct pgp_command_context *cctx = (struct pgp_command_context *) data;
70   int optional = (flags & M_FORMAT_OPTIONAL);
71
72   switch (op) {
73   case 'r':
74     {
75       if (!optional) {
76         snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
77         snprintf (dest, destlen, fmt, NONULL (cctx->ids));
78       }
79       else if (!cctx->ids)
80         optional = 0;
81       break;
82     }
83
84   case 'a':
85     {
86       if (!optional) {
87         snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
88         snprintf (dest, destlen, fmt, NONULL (cctx->signas));
89       }
90       else if (!cctx->signas)
91         optional = 0;
92       break;
93     }
94
95   case 's':
96     {
97       if (!optional) {
98         snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
99         snprintf (dest, destlen, fmt, NONULL (cctx->sig_fname));
100       }
101       else if (!cctx->sig_fname)
102         optional = 0;
103       break;
104     }
105
106   case 'f':
107     {
108       if (!optional) {
109         snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
110         snprintf (dest, destlen, fmt, NONULL (cctx->fname));
111       }
112       else if (!cctx->fname)
113         optional = 0;
114       break;
115     }
116
117   case 'p':
118     {
119       if (!optional) {
120         snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
121         snprintf (dest, destlen, fmt,
122                   cctx->need_passphrase ? "PGPPASSFD=0" : "");
123       }
124       else if (!cctx->need_passphrase || pgp_use_gpg_agent ())
125         optional = 0;
126       break;
127     }
128   default:
129     {
130       *dest = '\0';
131       break;
132     }
133   }
134
135   if (optional)
136     mutt_FormatString (dest, destlen, ifstring, _mutt_fmt_pgp_command, data,
137                        0);
138   else if (flags & M_FORMAT_OPTIONAL)
139     mutt_FormatString (dest, destlen, elsestring, _mutt_fmt_pgp_command, data,
140                        0);
141
142   return (src);
143 }
144
145 void mutt_pgp_command (char *d, size_t dlen, struct pgp_command_context *cctx,
146                        const char *fmt)
147 {
148   mutt_FormatString (d, dlen, NONULL (fmt), _mutt_fmt_pgp_command,
149                      (unsigned long) cctx, 0);
150   dprint (2, (debugfile, "mutt_pgp_command: %s\n", d));
151 }
152
153 /*
154  * Glue.
155  */
156
157
158 static pid_t pgp_invoke (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
159                          int pgpinfd, int pgpoutfd, int pgperrfd,
160                          short need_passphrase,
161                          const char *fname,
162                          const char *sig_fname,
163                          const char *signas,
164                          const char *ids, const char *format)
165 {
166   struct pgp_command_context cctx;
167   char cmd[HUGE_STRING];
168
169   memset (&cctx, 0, sizeof (cctx));
170
171   if (!format || !*format)
172     return (pid_t) - 1;
173
174   cctx.need_passphrase = need_passphrase;
175   cctx.fname = fname;
176   cctx.sig_fname = sig_fname;
177   cctx.signas = signas;
178   cctx.ids = ids;
179
180   mutt_pgp_command (cmd, sizeof (cmd), &cctx, format);
181
182   return mutt_create_filter_fd (cmd, pgpin, pgpout, pgperr,
183                                 pgpinfd, pgpoutfd, pgperrfd);
184 }
185
186
187 /*
188  * The exported interface.
189  * 
190  * This is historic and may be removed at some point.
191  *
192  */
193
194
195 pid_t pgp_invoke_decode (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
196                          int pgpinfd, int pgpoutfd, int pgperrfd,
197                          const char *fname, short need_passphrase)
198 {
199   return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
200                      need_passphrase, fname, NULL, NULL, NULL,
201                      PgpDecodeCommand);
202 }
203
204 pid_t pgp_invoke_verify (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
205                          int pgpinfd, int pgpoutfd, int pgperrfd,
206                          const char *fname, const char *sig_fname)
207 {
208   return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
209                      0, fname, sig_fname, NULL, NULL, PgpVerifyCommand);
210 }
211
212 pid_t pgp_invoke_decrypt (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
213                           int pgpinfd, int pgpoutfd, int pgperrfd,
214                           const char *fname)
215 {
216   return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
217                      1, fname, NULL, NULL, NULL, PgpDecryptCommand);
218 }
219
220 pid_t pgp_invoke_sign (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
221                        int pgpinfd, int pgpoutfd, int pgperrfd,
222                        const char *fname)
223 {
224   return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
225                      1, fname, NULL, PgpSignAs, NULL, PgpSignCommand);
226 }
227
228
229 pid_t pgp_invoke_encrypt (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
230                           int pgpinfd, int pgpoutfd, int pgperrfd,
231                           const char *fname, const char *uids, int sign)
232 {
233   if (sign)
234     return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
235                        1, fname, NULL, PgpSignAs, uids,
236                        PgpEncryptSignCommand);
237   else
238     return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
239                        0, fname, NULL, NULL, uids, PgpEncryptOnlyCommand);
240 }
241
242 pid_t pgp_invoke_traditional (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
243                               int pgpinfd, int pgpoutfd, int pgperrfd,
244                               const char *fname, const char *uids, int flags)
245 {
246   if (flags & ENCRYPT)
247     return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
248                        flags & SIGN ? 1 : 0, fname, NULL, PgpSignAs, uids,
249                        flags & SIGN ? PgpEncryptSignCommand :
250                        PgpEncryptOnlyCommand);
251   else
252     return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
253                        1, fname, NULL, PgpSignAs, NULL, PgpClearSignCommand);
254 }
255
256
257 void pgp_invoke_import (const char *fname)
258 {
259   char _fname[_POSIX_PATH_MAX + SHORT_STRING];
260   char cmd[HUGE_STRING];
261   struct pgp_command_context cctx;
262
263   memset (&cctx, 0, sizeof (cctx));
264
265   mutt_quote_filename (_fname, sizeof (_fname), fname);
266   cctx.fname = _fname;
267
268   mutt_pgp_command (cmd, sizeof (cmd), &cctx, PgpImportCommand);
269   mutt_system (cmd);
270 }
271
272 void pgp_invoke_getkeys (ADDRESS * addr)
273 {
274   char buff[LONG_STRING];
275   char tmp[LONG_STRING];
276   char cmd[HUGE_STRING];
277   int devnull;
278
279   char *personal;
280
281   struct pgp_command_context cctx;
282
283   if (!PgpGetkeysCommand)
284     return;
285
286   memset (&cctx, 0, sizeof (cctx));
287
288   personal = addr->personal;
289   addr->personal = NULL;
290
291   *tmp = '\0';
292   mutt_addrlist_to_local (addr);
293   rfc822_write_address_single (tmp, sizeof (tmp), addr, 0);
294   mutt_quote_filename (buff, sizeof (buff), tmp);
295
296   addr->personal = personal;
297
298   cctx.ids = buff;
299
300   mutt_pgp_command (cmd, sizeof (cmd), &cctx, PgpGetkeysCommand);
301
302   devnull = open ("/dev/null", O_RDWR);
303
304   if (!isendwin ())
305     mutt_message _("Fetching PGP key...");
306
307   mutt_system (cmd);
308
309   if (!isendwin ())
310     mutt_clear_error ();
311
312   close (devnull);
313 }
314
315 pid_t pgp_invoke_export (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
316                          int pgpinfd, int pgpoutfd, int pgperrfd,
317                          const char *uids)
318 {
319   return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
320                      0, NULL, NULL, NULL, uids, PgpExportCommand);
321 }
322
323 pid_t pgp_invoke_verify_key (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
324                              int pgpinfd, int pgpoutfd, int pgperrfd,
325                              const char *uids)
326 {
327   return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
328                      0, NULL, NULL, NULL, uids, PgpVerifyKeyCommand);
329 }
330
331 pid_t pgp_invoke_list_keys (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
332                             int pgpinfd, int pgpoutfd, int pgperrfd,
333                             pgp_ring_t keyring, LIST * hints)
334 {
335   char uids[HUGE_STRING];
336   char tmpuids[HUGE_STRING];
337   char quoted[HUGE_STRING];
338
339   *uids = '\0';
340
341   for (; hints; hints = hints->next) {
342     mutt_quote_filename (quoted, sizeof (quoted), (char *) hints->data);
343     snprintf (tmpuids, sizeof (tmpuids), "%s %s", uids, quoted);
344     strcpy (uids, tmpuids);     /* __STRCPY_CHECKED__ */
345   }
346
347   return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
348                      0, NULL, NULL, NULL, uids,
349                      keyring == PGP_SECRING ? PgpListSecringCommand :
350                      PgpListPubringCommand);
351 }