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