58a9467f5e15138988454914bbb403da43a599ee
[gnupg.git] / agent / trustlist.c
1 /* trustlist.c - Maintain the list of trusted keys
2  *      Copyright (C) 2002, 2004, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 #include <config.h>
23 #include <errno.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <assert.h>
29 #include <unistd.h>
30 #include <sys/stat.h>
31 #include <pth.h>
32
33 #include "agent.h"
34 #include <assuan.h> /* fixme: need a way to avoid assuan calls here */
35 #include "i18n.h"
36
37
38 /* A structure to store the information from the trust file. */
39 struct trustitem_s
40 {
41   int keyflag;            /* The keyflag:  '*', 'P' or 'S'. */
42   unsigned char fpr[20];  /* The binary fingerprint. */
43 };
44 typedef struct trustitem_s trustitem_t;
45
46 /* Malloced table and its allocated size with all trust items. */
47 static trustitem_t *trusttable; 
48 static size_t trusttablesize; 
49 /* A mutex used to protect the table. */
50 static pth_mutex_t trusttable_lock = PTH_MUTEX_INIT;
51
52
53
54 static const char headerblurb[] =
55 "# This is the list of trusted keys.  Comment lines, like this one, as\n"
56 "# well as empty lines are ignored.  Lines have a length limit but this\n"
57 "# is not serious limitation as the format of the entries is fixed and\n"
58 "# checked by gpg-agent.  A non-comment line starts with optional white\n"
59 "# space, followed by the SHA-1 fingerpint in hex, optionally followed\n"
60 "# by a flag character which my either be 'P', 'S' or '*'.  You should\n"
61 "# give the gpg-agent a HUP after editing this file.\n"
62 "\n\n"
63 "# Include the default trust list\n"
64 "include-default\n"
65 "\n";
66
67
68
69 \f
70 static void
71 lock_trusttable (void)
72 {
73   if (!pth_mutex_acquire (&trusttable_lock, 0, NULL))
74     log_fatal ("failed to acquire mutex in %s\n", __FILE__);
75 }
76
77 static void
78 unlock_trusttable (void)
79 {
80   if (!pth_mutex_release (&trusttable_lock))
81     log_fatal ("failed to release mutex in %s\n", __FILE__);
82 }
83
84
85
86 static gpg_error_t
87 read_one_trustfile (const char *fname, int allow_include,
88                     trustitem_t **addr_of_table, 
89                     size_t *addr_of_tablesize,
90                     int *addr_of_tableidx)
91 {
92   gpg_error_t err = 0;
93   FILE *fp;
94   int n, c;
95   char *p, line[256];
96   trustitem_t *table, *ti;
97   int tableidx;
98   size_t tablesize;
99   int lnr = 0;
100
101   table = *addr_of_table;
102   tablesize = *addr_of_tablesize;
103   tableidx = *addr_of_tableidx;
104
105   fp = fopen (fname, "r");
106   if (!fp)
107     {
108       err = gpg_error_from_syserror ();
109       log_error (_("error opening `%s': %s\n"), fname, gpg_strerror (err));
110       goto leave;
111     }
112
113   while (fgets (line, DIM(line)-1, fp))
114     {
115       lnr++;
116       
117       if (!*line || line[strlen(line)-1] != '\n')
118         {
119           /* Eat until end of line. */
120           while ( (c=getc (fp)) != EOF && c != '\n')
121             ;
122           err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
123                            : GPG_ERR_INCOMPLETE_LINE);
124           log_error (_("file `%s', line %d: %s\n"),
125                      fname, lnr, gpg_strerror (err));
126           continue;
127         }
128       line[strlen(line)-1] = 0; /* Chop the LF. */
129       
130       /* Allow for empty lines and spaces */
131       for (p=line; spacep (p); p++)
132         ;
133       if (!*p || *p == '#')
134         continue;
135   
136       if (!strncmp (p, "include-default", 15)
137           && (!p[15] || spacep (p+15)))
138         {
139           char *etcname;
140           gpg_error_t err2;
141
142           if (!allow_include)
143             {
144               log_error (_("statement \"%s\" ignored in `%s', line %d\n"),
145                          "include-default", fname, lnr);
146               continue;
147             }
148           /* fixme: Should check for trailing garbage.  */
149
150           etcname = make_filename (GNUPG_SYSCONFDIR, "trustlist.txt", NULL);
151           if ( !strcmp (etcname, fname) ) /* Same file. */
152             log_info (_("statement \"%s\" ignored in `%s', line %d\n"),
153                       "include-default", fname, lnr);
154           else if ( access (etcname, F_OK) && errno == ENOENT )
155             {
156               /* A non existent system trustlist is not an error.
157                  Just print a note. */
158               log_info (_("system trustlist `%s' not available\n"), etcname);
159             }
160           else
161             {
162               err2 = read_one_trustfile (etcname, 0,
163                                          &table, &tablesize, &tableidx);
164               if (err2)
165                 err = err2;
166             }
167           xfree (etcname);
168           
169           continue;
170         }
171
172       if (tableidx == tablesize)  /* Need more space. */
173         {
174           trustitem_t *tmp;
175           size_t tmplen;
176           
177           tmplen = tablesize + 20;
178           tmp = xtryrealloc (table, tmplen * sizeof *table);
179           if (!tmp)
180             {
181               err = gpg_error_from_syserror ();
182               goto leave;
183             }
184           table = tmp;
185           tablesize = tmplen;
186         }
187
188       ti = table + tableidx;
189
190       n = hexcolon2bin (p, ti->fpr, 20);
191       if (n < 0)
192         {
193           log_error (_("bad fingerprint in `%s', line %d\n"), fname, lnr);
194           err = gpg_error (GPG_ERR_BAD_DATA); 
195           continue;
196         }
197       p += n;
198       for (; spacep (p); p++)
199         ;
200       
201       if (!*p)
202         ti->keyflag = '*';
203       else if ( *p == 'P' || *p == 'p')
204         ti->keyflag = 'P';
205       else if ( *p == 'S' || *p == 's')
206         ti->keyflag = 'S';
207       else if ( *p == '*')
208         ti->keyflag = '*';
209       else
210         {
211           log_error (_("invalid keyflag in `%s', line %d\n"), fname, lnr);
212           err = gpg_error (GPG_ERR_BAD_DATA);
213           continue;
214         }
215       p++;
216       if ( *p && !spacep (p) )
217         {
218           log_error (_("invalid keyflag in `%s', line %d\n"), fname, lnr);
219           err = gpg_error (GPG_ERR_BAD_DATA);
220           continue;
221         }
222       /* Fixme: need to check for trailing garbage. */
223       tableidx++;
224     }
225   if ( !err && !feof (fp) )
226     {
227       err = gpg_error_from_syserror ();
228       log_error (_("error reading `%s', line %d: %s\n"),
229                  fname, lnr, gpg_strerror (err));
230     }
231
232  leave:
233   if (fp)
234     fclose (fp);
235   *addr_of_table = table;
236   *addr_of_tablesize = tablesize;
237   *addr_of_tableidx = tableidx;
238   return err;
239 }
240
241
242 /* Read the trust files and update the global table on success. */
243 static gpg_error_t
244 read_trustfiles (void)
245 {
246   gpg_error_t err;
247   trustitem_t *table, *ti;
248   int tableidx;
249   size_t tablesize;
250   char *fname;
251   int allow_include = 1;
252
253   tablesize = 10;
254   table = xtrycalloc (tablesize, sizeof *table);
255   if (!table)
256     return gpg_error_from_syserror ();
257   tableidx = 0;
258
259   fname = make_filename (opt.homedir, "trustlist.txt", NULL);
260   if ( access (fname, F_OK) )
261     {
262       if ( errno == ENOENT )
263         ; /* Silently ignore a non-existing trustfile.  */
264       else
265         {
266           err = gpg_error_from_syserror ();
267           log_error (_("error opening `%s': %s\n"), fname, gpg_strerror (err));
268         }
269       xfree (fname);
270       fname = make_filename (GNUPG_SYSCONFDIR, "trustlist.txt", NULL);
271       allow_include = 0;
272     }
273   err = read_one_trustfile (fname, allow_include,
274                             &table, &tablesize, &tableidx);
275   xfree (fname);
276
277   if (err)
278     {
279       xfree (table);
280       return err;
281     }
282
283   /* Fixme: we should drop duplicates and sort the table. */
284
285   ti = xtryrealloc (table, tableidx * sizeof *table);
286   if (!ti)
287     {
288       xfree (table);
289       return err;
290     }
291
292   lock_trusttable ();
293   xfree (trusttable);
294   trusttable = table;
295   trusttablesize = tableidx;
296   unlock_trusttable ();
297   return 0;
298 }
299
300
301
302 /* Check whether the given fpr is in our trustdb.  We expect FPR to be
303    an all uppercase hexstring of 40 characters. */
304 gpg_error_t 
305 agent_istrusted (const char *fpr)
306 {
307   gpg_error_t err;
308   trustitem_t *ti;
309   size_t len;
310   unsigned char fprbin[20];
311
312   if ( hexcolon2bin (fpr, fprbin, 20) < 0 )
313     return gpg_error (GPG_ERR_INV_VALUE);
314
315   if (!trusttable)
316     {
317       err = read_trustfiles ();
318       if (err)
319         {
320           log_error (_("error reading list of trusted root certificates\n"));
321           return err;
322         }
323     }
324
325   if (trusttable)
326     {
327       for (ti=trusttable, len = trusttablesize; len; ti++, len--)
328         if (!memcmp (ti->fpr, fprbin, 20))
329           return 0; /* Trusted. */
330     }
331   return gpg_error (GPG_ERR_NOT_TRUSTED);
332 }
333
334
335 /* Write all trust entries to FP. */
336 gpg_error_t 
337 agent_listtrusted (void *assuan_context)
338 {
339   trustitem_t *ti;
340   char key[51];
341   gpg_error_t err;
342   size_t len;
343
344   if (!trusttable)
345     {
346       err = read_trustfiles ();
347       if (err)
348         {
349           log_error (_("error reading list of trusted root certificates\n"));
350           return err;
351         }
352     }
353
354   if (trusttable)
355     {
356       /* We need to lock the table because the scheduler may interrupt
357          assuan_send_data and an other thread may then re-read the table. */
358       lock_trusttable ();
359       for (ti=trusttable, len = trusttablesize; len; ti++, len--)
360         {
361           bin2hex (ti->fpr, 20, key);
362           key[40] = ' ';
363           key[41] = ti->keyflag;
364           key[42] = '\n';
365           assuan_send_data (assuan_context, key, 43);
366           assuan_send_data (assuan_context, NULL, 0); /* flush */
367         }
368       unlock_trusttable ();
369     }
370
371   return 0;
372 }
373
374
375 /* Insert the given fpr into our trustdb.  We expect FPR to be an all
376    uppercase hexstring of 40 characters. FLAG is either 'P' or 'C'.
377    This function does first check whether that key has alreay been put
378    into the trustdb and returns success in this case.  Before a FPR
379    actually gets inserted, the user is asked by means of the pin-entry
380    whether this is actual wants he want to do.
381 */
382 gpg_error_t
383 agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag)
384 {
385   gpg_error_t err = 0;
386   char *desc;
387   char *fname;
388   FILE *fp;
389
390   /* Check whether we are at all allowed to modify the trustlist.
391      This is useful so that the trustlist may be a symlink to a global
392      trustlist with only admin priviliges to modify it.  Of course
393      this is not a secure way of denying access, but it avoids the
394      usual clicking on an Okay button most users are used to. */
395   fname = make_filename (opt.homedir, "trustlist.txt", NULL);
396   if ( access (fname, W_OK) && errno != ENOENT)
397     {
398       xfree (fname);
399       return gpg_error (GPG_ERR_EPERM);
400     }    
401   xfree (fname);
402
403   if (!agent_istrusted (fpr))
404     {
405       return 0; /* We already got this fingerprint.  Silently return
406                    success. */
407     }
408
409   /* This feature must explicitly been enabled. */
410   if (!opt.allow_mark_trusted)
411     return gpg_error (GPG_ERR_NOT_SUPPORTED);
412
413   /* Insert a new one. */
414   if (asprintf (&desc,
415                 /* TRANSLATORS: This prompt is shown by the Pinentry
416                    and has one special property: A "%%0A" is used by
417                    Pinentry to insert a line break.  The double
418                    percent sign is actually needed because it is also
419                    a printf format string.  If you need to insert a
420                    plain % sign, you need to encode it as "%%25".  The
421                    second "%s" gets replaced by a hexdecimal
422                    fingerprint string whereas the first one receives
423                    the name as store in the certificate. */
424                 _("Please verify that the certificate identified as:%%0A"
425                   "  \"%s\"%%0A"
426                   "has the fingerprint:%%0A"
427                   "  %s"), name, fpr) < 0 )
428     return out_of_core ();
429
430   /* TRANSLATORS: "Correct" is the label of a button and intended to
431      be hit if the fingerprint matches the one of the CA.  The other
432      button is "the default "Cancel" of the Pinentry. */
433   err = agent_get_confirmation (ctrl, desc, _("Correct"), NULL);
434   free (desc);
435   if (err)
436     return err;
437
438   if (asprintf (&desc,
439                 /* TRANSLATORS: This prompt is shown by the Pinentry
440                    and has one special property: A "%%0A" is used by
441                    Pinentry to insert a line break.  The double
442                    percent sign is actually needed because it is also
443                    a printf format string.  If you need to insert a
444                    plain % sign, you need to encode it as "%%25".  The
445                    "%s" gets replaced by the name as store in the
446                    certificate. */
447                 _("Do you ultimately trust%%0A"
448                   "  \"%s\"%%0A"
449                   "to correctly certify user certificates?"),
450                 name) < 0 )
451     return out_of_core ();
452
453   err = agent_get_confirmation (ctrl, desc, _("Yes"), _("No"));
454   free (desc);
455   if (err)
456     return err;
457
458   /* Now check again to avoid duplicates.  We take the lock to make
459      sure that nobody else plays with our file.  Frankly we don't work
460      with the trusttable but using this lock is just fine for our
461      purpose.  */
462   lock_trusttable ();
463   if (!agent_istrusted (fpr))
464     {
465       unlock_trusttable ();
466       return 0; 
467     }
468
469
470   fname = make_filename (opt.homedir, "trustlist.txt", NULL);
471   if ( access (fname, F_OK) && errno == ENOENT)
472     {
473       fp = fopen (fname, "wx"); /* Warning: "x" is a GNU extension. */
474       if (!fp)
475         {
476           err = gpg_error_from_syserror ();
477           log_error ("can't create `%s': %s\n", fname, gpg_strerror (err));
478           xfree (fname);
479           unlock_trusttable ();
480           return err;
481         }
482       fputs (headerblurb, fp);
483       fclose (fp);
484     }
485   fp = fopen (fname, "a+");
486   if (!fp)
487     {
488       err = gpg_error_from_syserror ();
489       log_error ("can't open `%s': %s\n", fname, gpg_strerror (err));
490       xfree (fname);
491       unlock_trusttable ();
492       return err;
493     }
494
495   /* Append the key. */
496   fputs ("\n# ", fp);
497   print_sanitized_string (fp, name, 0);
498   fprintf (fp, "\n%s %c\n", fpr, flag);
499   if (ferror (fp))
500     err = gpg_error_from_syserror ();
501   
502   if (fclose (fp))
503     err = gpg_error_from_syserror ();
504
505   if (!err)
506     agent_reload_trustlist ();
507   xfree (fname);
508   unlock_trusttable ();
509   return err;
510 }
511
512
513 /* This function may be called to force reloading of the
514    trustlist.  */
515 void
516 agent_reload_trustlist (void)
517 {
518   /* All we need to do is to delete the trusttable.  At the next
519      access it will get re-read. */
520   lock_trusttable ();
521   xfree (trusttable);
522   trusttable = NULL;
523   trusttablesize = 0;
524   unlock_trusttable ();
525 }