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