2004-08-17 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / agent / trustlist.c
bloba0b6b9861e028b62010418ff5b3f6829ee37c6b9
1 /* trustlist.c - Maintain the list of trusted keys
2 * Copyright (C) 2002, 2004 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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
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>
31 #include "agent.h"
32 #include <assuan.h> /* fixme: need a way to avoid assuan calls here */
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";
49 static FILE *trustfp;
50 static int trustfp_used; /* Counter to track usage of TRUSTFP. */
51 static int reload_trustlist_pending;
54 static int
55 open_list (int append)
57 char *fname;
59 fname = make_filename (opt.homedir, "trustlist.txt", NULL);
60 trustfp = fopen (fname, append? "a+":"r");
61 if (!trustfp && errno == ENOENT)
63 trustfp = fopen (fname, "wx");
64 if (!trustfp)
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;
71 fputs (headerblurb, trustfp);
72 fclose (trustfp);
73 trustfp = fopen (fname, append? "a+":"r");
76 if (!trustfp)
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;
84 /*FIXME: check the MAC */
86 return 0;
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 '*'.
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)
100 int rc;
101 int c, i, j;
102 char *p, line[256];
104 if (!trustfp)
106 rc = open_list (0);
107 if (rc)
108 return rc;
113 if (!fgets (line, DIM(line)-1, trustfp) )
115 if (feof (trustfp))
116 return -1;
117 return gpg_error (gpg_err_code_from_errno (errno));
120 if (!*line || line[strlen(line)-1] != '\n')
122 /* eat until end of line */
123 while ( (c=getc (trustfp)) != EOF && c != '\n')
125 return gpg_error (*line? GPG_ERR_LINE_TOO_LONG
126 : GPG_ERR_INCOMPLETE_LINE);
129 /* Allow for empty lines and spaces */
130 for (p=line; spacep (p); p++)
133 while (!*p || *p == '\n' || *p == '#');
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'))
141 log_error ("invalid formatted fingerprint in trustlist\n");
142 return gpg_error (GPG_ERR_BAD_DATA);
144 assert (p[i]);
145 if (p[i] == '\n')
146 *keyflag = '*';
147 else
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
158 log_error ("invalid keyflag in trustlist\n");
159 return gpg_error (GPG_ERR_BAD_DATA);
161 i++;
162 if ( !(spacep (p+i) || p[i] == '\n'))
164 log_error ("invalid keyflag in trustlist\n");
165 return gpg_error (GPG_ERR_BAD_DATA);
169 return 0;
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)
177 int rc;
178 static char key[41];
179 int keyflag;
181 trustfp_used++;
182 if (trustfp)
183 rewind (trustfp);
184 while (!(rc=read_list (key, &keyflag)))
186 if (!strcmp (key, fpr))
188 trustfp_used--;
189 return 0;
192 if (rc != -1)
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;
200 trustfp_used--;
201 return rc;
205 /* Write all trust entries to FP. */
206 int
207 agent_listtrusted (void *assuan_context)
209 int rc;
210 static char key[51];
211 int keyflag;
213 trustfp_used++;
214 if (trustfp)
215 rewind (trustfp);
216 while (!(rc=read_list (key, &keyflag)))
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 */
224 if (rc == -1)
225 rc = 0;
226 if (rc)
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;
234 trustfp_used--;
235 return rc;
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.
246 int
247 agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag)
249 int rc;
250 static char key[41];
251 int keyflag;
252 char *desc;
253 char *fname;
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)
264 xfree (fname);
265 return gpg_error (GPG_ERR_EPERM);
267 xfree (fname);
269 trustfp_used++;
270 if (trustfp)
271 rewind (trustfp);
272 while (!(rc=read_list (key, &keyflag)))
274 if (!strcmp (key, fpr))
275 return 0;
277 if (trustfp)
278 fclose (trustfp);
279 trustfp = NULL;
280 if (rc != -1)
282 trustfp_used--;
283 return rc; /* Error in the trustlist. */
286 /* This feature must explicitly been enabled. */
287 if (!opt.allow_mark_trusted)
289 trustfp_used--;
290 return gpg_error (GPG_ERR_NOT_SUPPORTED);
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 )
300 trustfp_used--;
301 return out_of_core ();
303 rc = agent_get_confirmation (ctrl, desc, "Correct", "No");
304 free (desc);
305 if (rc)
307 trustfp_used--;
308 return rc;
311 if (asprintf (&desc,
312 "Do you ultimately trust%%0A"
313 " \"%s\"%%0A"
314 "to correctly certify user certificates?",
315 name) < 0 )
317 trustfp_used--;
318 return out_of_core ();
320 rc = agent_get_confirmation (ctrl, desc, "Yes", "No");
321 free (desc);
322 if (rc)
324 trustfp_used--;
325 return rc;
328 /* Now check again to avoid duplicates. Also open in append mode now. */
329 rc = open_list (1);
330 if (rc)
332 trustfp_used--;
333 return rc;
335 rewind (trustfp);
336 while (!(rc=read_list (key, &keyflag)))
338 if (!strcmp (key, fpr))
340 trustfp_used--;
341 return 0;
344 if (rc != -1)
346 if (trustfp)
347 fclose (trustfp);
348 trustfp = NULL;
349 trustfp_used--;
350 return rc; /* Error in the trustlist. */
352 rc = 0;
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));
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;
371 void
372 agent_trustlist_housekeeping (void)
374 if (reload_trustlist_pending && !trustfp_used)
376 if (trustfp)
378 fclose (trustfp);
379 trustfp = NULL;
381 reload_trustlist_pending = 0;
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)
393 reload_trustlist_pending = 1;
394 agent_trustlist_housekeeping ();