chiark / gitweb /
doc: Document summary values of TOFU_STATS
[gnupg2.git] / sm / qualified.c
1 /* qualified.c - Routines related to qualified signatures
2  * Copyright (C) 2005, 2007 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 3 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, see <https://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdarg.h>
25 #include <assert.h>
26 #include <errno.h>
27
28 #include "gpgsm.h"
29 #include "i18n.h"
30 #include <ksba.h>
31
32
33 /* We open the file only once and keep the open file pointer as well
34    as the name of the file here.  Note that, a listname not equal to
35    NULL indicates that this module has been intialized and if the
36    LISTFP is also NULL, no list of qualified signatures exists. */
37 static char *listname;
38 static FILE *listfp;
39
40
41 /* Read the trustlist and return entry by entry.  KEY must point to a
42    buffer of at least 41 characters. COUNTRY shall be a buffer of at
43    least 3 characters to receive the country code of that qualified
44    signature (i.e. "de" for German and "be" for Belgium).
45
46    Reading a valid entry returns 0, EOF is indicated by GPG_ERR_EOF
47    and any other error condition is indicated by the appropriate error
48    code. */
49 static gpg_error_t
50 read_list (char *key, char *country, int *lnr)
51 {
52   gpg_error_t err;
53   int c, i, j;
54   char *p, line[256];
55
56   *key = 0;
57   *country = 0;
58
59   if (!listname)
60     {
61       listname = make_filename (gnupg_datadir (), "qualified.txt", NULL);
62       listfp = fopen (listname, "r");
63       if (!listfp && errno != ENOENT)
64         {
65           err = gpg_error_from_syserror ();
66           log_error (_("can't open '%s': %s\n"), listname, gpg_strerror (err));
67           return err;
68         }
69     }
70
71   if (!listfp)
72     return gpg_error (GPG_ERR_EOF);
73
74   do
75     {
76       if (!fgets (line, DIM(line)-1, listfp) )
77         {
78           if (feof (listfp))
79             return gpg_error (GPG_ERR_EOF);
80           return gpg_error_from_syserror ();
81         }
82
83       if (!*line || line[strlen(line)-1] != '\n')
84         {
85           /* Eat until end of line. */
86           while ( (c=getc (listfp)) != EOF && c != '\n')
87             ;
88           return gpg_error (*line? GPG_ERR_LINE_TOO_LONG
89                                  : GPG_ERR_INCOMPLETE_LINE);
90         }
91       ++*lnr;
92
93       /* Allow for empty lines and spaces */
94       for (p=line; spacep (p); p++)
95         ;
96     }
97   while (!*p || *p == '\n' || *p == '#');
98
99   for (i=j=0; (p[i] == ':' || hexdigitp (p+i)) && j < 40; i++)
100     if ( p[i] != ':' )
101       key[j++] = p[i] >= 'a'? (p[i] & 0xdf): p[i];
102   key[j] = 0;
103   if (j != 40 || !(spacep (p+i) || p[i] == '\n'))
104     {
105       log_error (_("invalid formatted fingerprint in '%s', line %d\n"),
106                  listname, *lnr);
107       return gpg_error (GPG_ERR_BAD_DATA);
108     }
109   assert (p[i]);
110   i++;
111   while (spacep (p+i))
112     i++;
113   if ( p[i] >= 'a' && p[i] <= 'z'
114        && p[i+1] >= 'a' && p[i+1] <= 'z'
115        && (spacep (p+i+2) || p[i+2] == '\n'))
116     {
117       country[0] = p[i];
118       country[1] = p[i+1];
119       country[2] = 0;
120     }
121   else
122     {
123       log_error (_("invalid country code in '%s', line %d\n"), listname, *lnr);
124       return gpg_error (GPG_ERR_BAD_DATA);
125     }
126
127   return 0;
128 }
129
130
131
132
133 /* Check whether the certificate CERT is included in the list of
134    qualified certificates.  This list is similar to the "trustlist.txt"
135    as maintained by gpg-agent and includes fingerprints of root
136    certificates to be used for qualified (legally binding like
137    handwritten) signatures.  We keep this list system wide and not
138    per user because it is not a decision of the user.
139
140    Returns: 0 if the certificate is included.  GPG_ERR_NOT_FOUND if it
141    is not in the list or any other error (e.g. if no list of
142    qualified signatures is available.  If COUNTRY has not been passed
143    as NULL a string witha maximum length of 2 will be copied into it;
144    thus the caller needs to provide a buffer of length 3. */
145 gpg_error_t
146 gpgsm_is_in_qualified_list (ctrl_t ctrl, ksba_cert_t cert, char *country)
147 {
148   gpg_error_t err;
149   char *fpr;
150   char key[41];
151   char mycountry[3];
152   int lnr = 0;
153
154   (void)ctrl;
155
156   if (country)
157     *country = 0;
158
159   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
160   if (!fpr)
161     return gpg_error (GPG_ERR_GENERAL);
162
163   if (listfp)
164     {
165       /* W32ce has no rewind, thus we use the equivalent code.  */
166       fseek (listfp, 0, SEEK_SET);
167       clearerr (listfp);
168     }
169   while (!(err = read_list (key, mycountry, &lnr)))
170     {
171       if (!strcmp (key, fpr))
172         break;
173     }
174   if (gpg_err_code (err) == GPG_ERR_EOF)
175     err = gpg_error (GPG_ERR_NOT_FOUND);
176
177   if (!err && country)
178     strcpy (country, mycountry);
179
180   xfree (fpr);
181   return err;
182 }
183
184
185 /* We know that CERT is a qualified certificate.  Ask the user for
186    consent to actually create a signature using this certificate.
187    Returns: 0 for yes, GPG_ERR_CANCEL for no or any other error
188    code. */
189 gpg_error_t
190 gpgsm_qualified_consent (ctrl_t ctrl, ksba_cert_t cert)
191 {
192   gpg_error_t err;
193   char *name, *subject, *buffer, *p;
194   const char *s;
195   char *orig_codeset = NULL;
196
197   name = ksba_cert_get_subject (cert, 0);
198   if (!name)
199     return gpg_error (GPG_ERR_GENERAL);
200   subject = gpgsm_format_name2 (name, 0);
201   ksba_free (name); name = NULL;
202
203   orig_codeset = i18n_switchto_utf8 ();
204
205   if (asprintf (&name,
206                 _("You are about to create a signature using your "
207                   "certificate:\n"
208                   "\"%s\"\n"
209                   "This will create a qualified signature by law "
210                   "equated to a handwritten signature.\n\n%s%s"
211                   "Are you really sure that you want to do this?"),
212                 subject? subject:"?",
213                 opt.qualsig_approval?
214                 "":
215                 _("Note, that this software is not officially approved "
216                   "to create or verify such signatures.\n"),
217                 opt.qualsig_approval? "":"\n"
218                 ) < 0 )
219     err = gpg_error_from_syserror ();
220   else
221     err = 0;
222
223   i18n_switchback (orig_codeset);
224   xfree (subject);
225
226   if (err)
227     return err;
228
229   buffer = p = xtrymalloc (strlen (name) * 3 + 1);
230   if (!buffer)
231     {
232       err = gpg_error_from_syserror ();
233       free (name);
234       return err;
235     }
236   for (s=name; *s; s++)
237     {
238       if (*s < ' ' || *s == '+')
239         {
240           sprintf (p, "%%%02X", *(unsigned char *)s);
241           p += 3;
242         }
243       else if (*s == ' ')
244         *p++ = '+';
245       else
246         *p++ = *s;
247     }
248   *p = 0;
249   free (name);
250
251
252   err = gpgsm_agent_get_confirmation (ctrl, buffer);
253
254   xfree (buffer);
255   return err;
256 }
257
258
259 /* Popup a prompt to inform the user that the signature created is not
260    a qualified one.  This is of course only done if we know that we
261    have been approved. */
262 gpg_error_t
263 gpgsm_not_qualified_warning (ctrl_t ctrl, ksba_cert_t cert)
264 {
265   gpg_error_t err;
266   char *name, *subject, *buffer, *p;
267   const char *s;
268   char *orig_codeset;
269
270   if (!opt.qualsig_approval)
271     return 0;
272
273   name = ksba_cert_get_subject (cert, 0);
274   if (!name)
275     return gpg_error (GPG_ERR_GENERAL);
276   subject = gpgsm_format_name2 (name, 0);
277   ksba_free (name); name = NULL;
278
279   orig_codeset = i18n_switchto_utf8 ();
280
281   if (asprintf (&name,
282                 _("You are about to create a signature using your "
283                   "certificate:\n"
284                   "\"%s\"\n"
285                   "Note, that this certificate will NOT create a "
286                   "qualified signature!"),
287                 subject? subject:"?") < 0 )
288     err = gpg_error_from_syserror ();
289   else
290     err = 0;
291
292   i18n_switchback (orig_codeset);
293   xfree (subject);
294
295   if (err)
296     return err;
297
298   buffer = p = xtrymalloc (strlen (name) * 3 + 1);
299   if (!buffer)
300     {
301       err = gpg_error_from_syserror ();
302       free (name);
303       return err;
304     }
305   for (s=name; *s; s++)
306     {
307       if (*s < ' ' || *s == '+')
308         {
309           sprintf (p, "%%%02X", *(unsigned char *)s);
310           p += 3;
311         }
312       else if (*s == ' ')
313         *p++ = '+';
314       else
315         *p++ = *s;
316     }
317   *p = 0;
318   free (name);
319
320
321   err = gpgsm_agent_get_confirmation (ctrl, buffer);
322
323   xfree (buffer);
324   return err;
325 }