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