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