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
32
#include <assuan.h> /* fixme: need a way to avoid assuan calls here */
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"
46
"# NOTE: You should give the gpg-agent a HUP after editing this file.\n"
51
static int trustfp_used; /* Counter to track usage of TRUSTFP. */
52
static int reload_trustlist_pending;
56
open_list (int append)
60
fname = make_filename (opt.homedir, "trustlist.txt", NULL);
61
trustfp = fopen (fname, append? "a+":"r");
62
if (!trustfp && errno == ENOENT)
64
trustfp = fopen (fname, "wx");
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));
72
fputs (headerblurb, trustfp);
74
trustfp = fopen (fname, append? "a+":"r");
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));
85
/*FIXME: check the MAC */
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',
96
Reading a valid entry return 0, EOF returns -1 any other error
97
returns the appropriate error code. */
99
read_list (char *key, int *keyflag)
114
if (!fgets (line, DIM(line)-1, trustfp) )
118
return gpg_error (gpg_err_code_from_errno (errno));
121
if (!*line || line[strlen(line)-1] != '\n')
123
/* eat until end of line */
124
while ( (c=getc (trustfp)) != EOF && c != '\n')
126
return gpg_error (*line? GPG_ERR_LINE_TOO_LONG
127
: GPG_ERR_INCOMPLETE_LINE);
130
/* Allow for empty lines and spaces */
131
for (p=line; spacep (p); p++)
134
while (!*p || *p == '\n' || *p == '#');
136
for (i=j=0; (p[i] == ':' || hexdigitp (p+i)) && j < 40; i++)
138
key[j++] = p[i] >= 'a'? (p[i] & 0xdf): p[i];
140
if (j!=40 || !(spacep (p+i) || p[i] == '\n'))
142
log_error ("invalid formatted fingerprint in trustlist\n");
143
return gpg_error (GPG_ERR_BAD_DATA);
151
if ( p[i] == 'P' || p[i] == 'p')
153
else if ( p[i] == 'S' || p[i] == 's')
155
else if ( p[i] == '*')
159
log_error ("invalid keyflag in trustlist\n");
160
return gpg_error (GPG_ERR_BAD_DATA);
163
if ( !(spacep (p+i) || p[i] == '\n'))
165
log_error ("invalid keyflag in trustlist\n");
166
return gpg_error (GPG_ERR_BAD_DATA);
173
/* Check whether the given fpr is in our trustdb. We expect FPR to be
174
an all uppercase hexstring of 40 characters. */
176
agent_istrusted (const char *fpr)
185
while (!(rc=read_list (key, &keyflag)))
187
if (!strcmp (key, fpr))
195
/* Error in the trustdb - close it to give the user a chance for
206
/* Write all trust entries to FP. */
208
agent_listtrusted (void *assuan_context)
217
while (!(rc=read_list (key, &keyflag)))
222
assuan_send_data (assuan_context, key, 43);
223
assuan_send_data (assuan_context, NULL, 0); /* flush */
229
/* Error in the trustdb - close it to give the user a chance for
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.
248
agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag)
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)
266
return gpg_error (GPG_ERR_EPERM);
273
while (!(rc=read_list (key, &keyflag)))
275
if (!strcmp (key, fpr))
284
return rc; /* Error in the trustlist. */
287
/* This feature must explicitly been enabled. */
288
if (!opt.allow_mark_trusted)
291
return gpg_error (GPG_ERR_NOT_SUPPORTED);
294
/* Insert a new one. */
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"
307
"has the fingerprint:%%0A"
308
" %s"), name, fpr) < 0 )
311
return out_of_core ();
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);
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
334
_("Do you ultimately trust%%0A"
336
"to correctly certify user certificates?"),
340
return out_of_core ();
342
rc = agent_get_confirmation (ctrl, desc, _("Yes"), _("No"));
350
/* Now check again to avoid duplicates. Also open in append mode now. */
358
while (!(rc=read_list (key, &keyflag)))
360
if (!strcmp (key, fpr))
372
return rc; /* Error in the trustlist. */
376
/* Append the key. */
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));
384
/* close because we are in append mode */
385
if (fclose (trustfp))
386
rc = gpg_error (gpg_err_code_from_errno (errno));
394
agent_trustlist_housekeeping (void)
396
if (reload_trustlist_pending && !trustfp_used)
403
reload_trustlist_pending = 0;
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. */
413
agent_reload_trustlist (void)
415
reload_trustlist_pending = 1;
416
agent_trustlist_housekeeping ();