* command.c (cmd_updatestartuptty): New.
[gnupg.git] / agent / trustlist.c
1 /* trustlist.c - Maintain the list of trusted keys
2  *      Copyright (C) 2002, 2004 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <assert.h>
28 #include <unistd.h>
29 #include <sys/stat.h>
30
31 #include "agent.h"
32 #include <assuan.h> /* fixme: need a way to avoid assuan calls here */
33 #include "i18n.h"
34
35 static const char headerblurb[] =
36 "# This is the list of trusted keys.  Comment lines, like this one, as\n"
37 "# well as empty lines are ignored. The entire file may be integrity\n"
38 "# protected by the use of a MAC, so changing the file does not make\n"
39 "# sense without the knowledge of the MAC key.  Lines do have a length\n"
40 "# limit but this is not serious limitation as the format of the\n"
41 "# entries is fixed and checked by gpg-agent: A non-comment line starts\n"
42 "# with optional white spaces, followed by the SHA-1 fingerpint in hex,\n"
43 "# optionally followed by a flag character which my either be 'P', 'S'\n"
44 "# or '*'. Additional data, delimited by white space, is ignored.\n"
45 "#\n"
46 "# NOTE: You should give the gpg-agent a HUP after editing this file.\n"
47 "\n";
48
49
50 static FILE *trustfp;
51 static int   trustfp_used; /* Counter to track usage of TRUSTFP. */
52 static int   reload_trustlist_pending;
53
54
55 static int
56 open_list (int append)
57 {
58   char *fname;
59
60   fname = make_filename (opt.homedir, "trustlist.txt", NULL);
61   trustfp = fopen (fname, append? "a+":"r");
62   if (!trustfp && errno == ENOENT)
63     {
64       trustfp = fopen (fname, "wx");
65       if (!trustfp)
66         {
67           gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
68           log_error ("can't create `%s': %s\n", fname, strerror (errno));
69           xfree (fname);
70           return tmperr;
71         }
72       fputs (headerblurb, trustfp);
73       fclose (trustfp);
74       trustfp = fopen (fname, append? "a+":"r");
75     }
76
77   if (!trustfp)
78     {
79       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
80       log_error ("can't open `%s': %s\n", fname, strerror (errno));
81       xfree (fname);
82       return tmperr;
83     }
84
85   /*FIXME: check the MAC */
86
87   return 0;
88 }
89
90
91
92 /* Read the trustlist and return entry by entry.  KEY must point to a
93    buffer of at least 41 characters. KEYFLAG does return either 'P',
94    'S' or '*'.
95
96    Reading a valid entry return 0, EOF returns -1 any other error
97    returns the appropriate error code. */
98 static int
99 read_list (char *key, int *keyflag)
100 {
101   int rc;
102   int c, i, j;
103   char *p, line[256];
104   
105   if (!trustfp)
106     {
107       rc = open_list (0);
108       if (rc)
109         return rc;
110     }
111
112   do
113     {
114       if (!fgets (line, DIM(line)-1, trustfp) )
115         {
116           if (feof (trustfp))
117             return -1;
118           return gpg_error (gpg_err_code_from_errno (errno));
119         }
120       
121       if (!*line || line[strlen(line)-1] != '\n')
122         {
123           /* eat until end of line */
124           while ( (c=getc (trustfp)) != EOF && c != '\n')
125             ;
126           return gpg_error (*line? GPG_ERR_LINE_TOO_LONG
127                                  : GPG_ERR_INCOMPLETE_LINE);
128         }
129       
130       /* Allow for empty lines and spaces */
131       for (p=line; spacep (p); p++)
132         ;
133     }
134   while (!*p || *p == '\n' || *p == '#');
135   
136   for (i=j=0; (p[i] == ':' || hexdigitp (p+i)) && j < 40; i++)
137     if ( p[i] != ':' )
138       key[j++] = p[i] >= 'a'? (p[i] & 0xdf): p[i];
139   key[j] = 0;
140   if (j!=40 || !(spacep (p+i) || p[i] == '\n'))
141     {
142       log_error ("invalid formatted fingerprint in trustlist\n");
143       return gpg_error (GPG_ERR_BAD_DATA);
144     }
145   assert (p[i]);
146   if (p[i] == '\n')
147     *keyflag = '*';
148   else 
149     {
150       i++;
151       if ( p[i] == 'P' || p[i] == 'p')
152         *keyflag = 'P';
153       else if ( p[i] == 'S' || p[i] == 's')
154         *keyflag = 'S';
155       else if ( p[i] == '*')
156         *keyflag = '*';
157       else
158         {
159           log_error ("invalid keyflag in trustlist\n");
160           return gpg_error (GPG_ERR_BAD_DATA);
161         }
162       i++;
163       if ( !(spacep (p+i) || p[i] == '\n'))
164         {
165           log_error ("invalid keyflag in trustlist\n");
166           return gpg_error (GPG_ERR_BAD_DATA);
167         }
168     }
169
170   return 0;
171 }
172
173 /* Check whether the given fpr is in our trustdb.  We expect FPR to be
174    an all uppercase hexstring of 40 characters. */
175 int 
176 agent_istrusted (const char *fpr)
177 {
178   int rc;
179   static char key[41];
180   int keyflag;
181
182   trustfp_used++;
183   if (trustfp)
184     rewind (trustfp);
185   while (!(rc=read_list (key, &keyflag)))
186     {
187       if (!strcmp (key, fpr))
188         {
189           trustfp_used--;
190           return 0;
191         }
192     }
193   if (rc != -1)
194     {
195       /* Error in the trustdb - close it to give the user a chance for
196          correction */
197       if (trustfp)
198         fclose (trustfp);
199       trustfp = NULL;
200     }
201   trustfp_used--;
202   return rc;
203 }
204
205
206 /* Write all trust entries to FP. */
207 int 
208 agent_listtrusted (void *assuan_context)
209 {
210   int rc;
211   static char key[51];
212   int keyflag;
213
214   trustfp_used++;
215   if (trustfp)
216     rewind (trustfp);
217   while (!(rc=read_list (key, &keyflag)))
218     {
219       key[40] = ' ';
220       key[41] = keyflag;
221       key[42] = '\n';
222       assuan_send_data (assuan_context, key, 43);
223       assuan_send_data (assuan_context, NULL, 0); /* flush */
224     } 
225   if (rc == -1)
226     rc = 0;
227   if (rc)
228     {
229       /* Error in the trustdb - close it to give the user a chance for
230          correction */
231       if (trustfp)
232         fclose (trustfp);
233       trustfp = NULL;
234     }
235   trustfp_used--;
236   return rc;
237 }
238
239
240 /* Insert the given fpr into our trustdb.  We expect FPR to be an all
241    uppercase hexstring of 40 characters. FLAG is either 'P' or 'C'.
242    This function does first check whether that key has alreay been put
243    into the trustdb and returns success in this case.  Before a FPR
244    actually gets inserted, the user is asked by means of the pin-entry
245    whether this is actual wants he want to do.
246 */
247 int 
248 agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag)
249 {
250   int rc;
251   static char key[41];
252   int keyflag;
253   char *desc;
254   char *fname;
255
256   /* Check whether we are at all allowed to modify the trustlist.
257      This is useful so that the trustlist may be a symlink to a global
258      trustlist with only admin priviliges to modify it.  Of course
259      this is not a secure way of denying access, but it avoids the
260      usual clicking on an Okay buttun thing most users are used to. */
261   fname = make_filename (opt.homedir, "trustlist.txt", NULL);
262   rc = access (fname, W_OK);
263   if (rc && errno != ENOENT)
264     {
265       xfree (fname);
266       return gpg_error (GPG_ERR_EPERM);
267     }    
268   xfree (fname);
269
270   trustfp_used++;
271   if (trustfp)
272     rewind (trustfp);
273   while (!(rc=read_list (key, &keyflag)))
274     {
275       if (!strcmp (key, fpr))
276         return 0;
277     }
278   if (trustfp)
279     fclose (trustfp);
280   trustfp = NULL;
281   if (rc != -1)
282     {
283       trustfp_used--;
284       return rc;   /* Error in the trustlist. */
285     }
286
287   /* This feature must explicitly been enabled. */
288   if (!opt.allow_mark_trusted)
289     {
290       trustfp_used--;
291       return gpg_error (GPG_ERR_NOT_SUPPORTED);
292     }
293
294   /* Insert a new one. */
295   if (asprintf (&desc,
296                 /* TRANSLATORS: This prompt is shown by the Pinentry
297                    and has one special property: A "%%0A" is used by
298                    Pinentry to insert a line break.  The double
299                    percent sign is actually needed because it is also
300                    a printf format string.  If you need to insert a
301                    plain % sign, you need to encode it as "%%25".  The
302                    second "%s" gets replaced by a hexdecimal
303                    fingerprint string whereas the first one receives
304                    the name as store in the certificate. */
305                 _("Please verify that the certificate identified as:%%0A"
306                   "  \"%s\"%%0A"
307                   "has the fingerprint:%%0A"
308                   "  %s"), name, fpr) < 0 )
309     {
310       trustfp_used--;
311       return out_of_core ();
312     }
313
314   /* TRANSLATORS: "Correct" is the label of a button and intended to
315      be hit if the fingerprint matches the one of the CA.  The other
316      button is "the default "Cancel" of the Pinentry. */
317   rc = agent_get_confirmation (ctrl, desc, _("Correct"), NULL);
318   free (desc);
319   if (rc)
320     {
321       trustfp_used--;
322       return rc;
323     }
324
325   if (asprintf (&desc,
326                 /* TRANSLATORS: This prompt is shown by the Pinentry
327                    and has one special property: A "%%0A" is used by
328                    Pinentry to insert a line break.  The double
329                    percent sign is actually needed because it is also
330                    a printf format string.  If you need to insert a
331                    plain % sign, you need to encode it as "%%25".  The
332                    "%s" gets replaced by the name as store in the
333                    certificate. */
334                 _("Do you ultimately trust%%0A"
335                   "  \"%s\"%%0A"
336                   "to correctly certify user certificates?"),
337                 name) < 0 )
338     {
339       trustfp_used--;
340       return out_of_core ();
341     }
342   rc = agent_get_confirmation (ctrl, desc, _("Yes"), _("No"));
343   free (desc);
344   if (rc)
345     {
346       trustfp_used--;
347       return rc;
348     }
349
350   /* Now check again to avoid duplicates.  Also open in append mode now. */
351   rc = open_list (1);
352   if (rc)
353     {
354       trustfp_used--;
355       return rc;
356     }
357   rewind (trustfp);
358   while (!(rc=read_list (key, &keyflag)))
359     {
360       if (!strcmp (key, fpr))
361         {
362           trustfp_used--;
363           return 0;
364         }
365     }
366   if (rc != -1)
367     {
368       if (trustfp)
369         fclose (trustfp);
370       trustfp = NULL;
371       trustfp_used--;
372       return rc;   /* Error in the trustlist. */
373     }
374   rc = 0;
375
376   /* Append the key. */
377   fflush (trustfp);
378   fputs ("\n# ", trustfp);
379   print_sanitized_string (trustfp, name, 0);
380   fprintf (trustfp, "\n%s %c\n", fpr, flag);
381   if (ferror (trustfp))
382     rc = gpg_error (gpg_err_code_from_errno (errno));
383   
384   /* close because we are in append mode */
385   if (fclose (trustfp))
386     rc = gpg_error (gpg_err_code_from_errno (errno));
387   trustfp = NULL;
388   trustfp_used--;
389   return rc;
390 }
391
392
393 void
394 agent_trustlist_housekeeping (void)
395 {
396   if (reload_trustlist_pending && !trustfp_used)
397     {
398       if (trustfp)
399         {
400           fclose (trustfp);
401           trustfp = NULL;
402         }
403       reload_trustlist_pending = 0;
404     }
405 }
406
407
408 /* Not all editors are editing files in place, thus a changes
409    trustlist.txt won't be recognozed if we keep the file descriptor
410    open. This function may be used to explicitly close that file
411    descriptor, which will force a reopen in turn. */
412 void
413 agent_reload_trustlist (void)
414 {
415   reload_trustlist_pending = 1;
416   agent_trustlist_housekeeping ();
417 }