Line data Source code
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 <http://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 0 : 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 0 : *key = 0;
57 0 : *country = 0;
58 :
59 0 : if (!listname)
60 : {
61 0 : listname = make_filename (gnupg_datadir (), "qualified.txt", NULL);
62 0 : listfp = fopen (listname, "r");
63 0 : if (!listfp && errno != ENOENT)
64 : {
65 0 : err = gpg_error_from_syserror ();
66 0 : log_error (_("can't open '%s': %s\n"), listname, gpg_strerror (err));
67 0 : return err;
68 : }
69 : }
70 :
71 0 : if (!listfp)
72 0 : return gpg_error (GPG_ERR_EOF);
73 :
74 : do
75 : {
76 0 : if (!fgets (line, DIM(line)-1, listfp) )
77 : {
78 0 : if (feof (listfp))
79 0 : return gpg_error (GPG_ERR_EOF);
80 0 : return gpg_error_from_syserror ();
81 : }
82 :
83 0 : if (!*line || line[strlen(line)-1] != '\n')
84 : {
85 : /* Eat until end of line. */
86 0 : while ( (c=getc (listfp)) != EOF && c != '\n')
87 : ;
88 0 : return gpg_error (*line? GPG_ERR_LINE_TOO_LONG
89 : : GPG_ERR_INCOMPLETE_LINE);
90 : }
91 0 : ++*lnr;
92 :
93 : /* Allow for empty lines and spaces */
94 0 : for (p=line; spacep (p); p++)
95 : ;
96 : }
97 0 : while (!*p || *p == '\n' || *p == '#');
98 :
99 0 : for (i=j=0; (p[i] == ':' || hexdigitp (p+i)) && j < 40; i++)
100 0 : if ( p[i] != ':' )
101 0 : key[j++] = p[i] >= 'a'? (p[i] & 0xdf): p[i];
102 0 : key[j] = 0;
103 0 : if (j != 40 || !(spacep (p+i) || p[i] == '\n'))
104 : {
105 0 : log_error (_("invalid formatted fingerprint in '%s', line %d\n"),
106 : listname, *lnr);
107 0 : return gpg_error (GPG_ERR_BAD_DATA);
108 : }
109 0 : assert (p[i]);
110 0 : i++;
111 0 : while (spacep (p+i))
112 0 : i++;
113 0 : if ( p[i] >= 'a' && p[i] <= 'z'
114 0 : && p[i+1] >= 'a' && p[i+1] <= 'z'
115 0 : && (spacep (p+i+2) || p[i+2] == '\n'))
116 : {
117 0 : country[0] = p[i];
118 0 : country[1] = p[i+1];
119 0 : country[2] = 0;
120 : }
121 : else
122 : {
123 0 : log_error (_("invalid country code in '%s', line %d\n"), listname, *lnr);
124 0 : return gpg_error (GPG_ERR_BAD_DATA);
125 : }
126 :
127 0 : 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 0 : 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 0 : int lnr = 0;
153 :
154 : (void)ctrl;
155 :
156 0 : if (country)
157 0 : *country = 0;
158 :
159 0 : fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
160 0 : if (!fpr)
161 0 : return gpg_error (GPG_ERR_GENERAL);
162 :
163 0 : if (listfp)
164 : {
165 : /* W32ce has no rewind, thus we use the equivalent code. */
166 0 : fseek (listfp, 0, SEEK_SET);
167 0 : clearerr (listfp);
168 : }
169 0 : while (!(err = read_list (key, mycountry, &lnr)))
170 : {
171 0 : if (!strcmp (key, fpr))
172 0 : break;
173 : }
174 0 : if (gpg_err_code (err) == GPG_ERR_EOF)
175 0 : err = gpg_error (GPG_ERR_NOT_FOUND);
176 :
177 0 : if (!err && country)
178 0 : strcpy (country, mycountry);
179 :
180 0 : xfree (fpr);
181 0 : 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 0 : 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 0 : char *orig_codeset = NULL;
196 :
197 0 : name = ksba_cert_get_subject (cert, 0);
198 0 : if (!name)
199 0 : return gpg_error (GPG_ERR_GENERAL);
200 0 : subject = gpgsm_format_name2 (name, 0);
201 0 : ksba_free (name); name = NULL;
202 :
203 0 : orig_codeset = i18n_switchto_utf8 ();
204 :
205 0 : if (asprintf (&name,
206 0 : _("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 0 : opt.qualsig_approval?
214 : "":
215 : _("Note, that this software is not officially approved "
216 : "to create or verify such signatures.\n"),
217 0 : opt.qualsig_approval? "":"\n"
218 : ) < 0 )
219 0 : err = gpg_error_from_syserror ();
220 : else
221 0 : err = 0;
222 :
223 0 : i18n_switchback (orig_codeset);
224 0 : xfree (subject);
225 :
226 0 : if (err)
227 0 : return err;
228 :
229 0 : buffer = p = xtrymalloc (strlen (name) * 3 + 1);
230 0 : if (!buffer)
231 : {
232 0 : err = gpg_error_from_syserror ();
233 0 : free (name);
234 0 : return err;
235 : }
236 0 : for (s=name; *s; s++)
237 : {
238 0 : if (*s < ' ' || *s == '+')
239 : {
240 0 : sprintf (p, "%%%02X", *(unsigned char *)s);
241 0 : p += 3;
242 : }
243 0 : else if (*s == ' ')
244 0 : *p++ = '+';
245 : else
246 0 : *p++ = *s;
247 : }
248 0 : *p = 0;
249 0 : free (name);
250 :
251 :
252 0 : err = gpgsm_agent_get_confirmation (ctrl, buffer);
253 :
254 0 : xfree (buffer);
255 0 : 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 0 : 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 0 : if (!opt.qualsig_approval)
271 0 : return 0;
272 :
273 0 : name = ksba_cert_get_subject (cert, 0);
274 0 : if (!name)
275 0 : return gpg_error (GPG_ERR_GENERAL);
276 0 : subject = gpgsm_format_name2 (name, 0);
277 0 : ksba_free (name); name = NULL;
278 :
279 0 : orig_codeset = i18n_switchto_utf8 ();
280 :
281 0 : if (asprintf (&name,
282 0 : _("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 0 : err = gpg_error_from_syserror ();
289 : else
290 0 : err = 0;
291 :
292 0 : i18n_switchback (orig_codeset);
293 0 : xfree (subject);
294 :
295 0 : if (err)
296 0 : return err;
297 :
298 0 : buffer = p = xtrymalloc (strlen (name) * 3 + 1);
299 0 : if (!buffer)
300 : {
301 0 : err = gpg_error_from_syserror ();
302 0 : free (name);
303 0 : return err;
304 : }
305 0 : for (s=name; *s; s++)
306 : {
307 0 : if (*s < ' ' || *s == '+')
308 : {
309 0 : sprintf (p, "%%%02X", *(unsigned char *)s);
310 0 : p += 3;
311 : }
312 0 : else if (*s == ' ')
313 0 : *p++ = '+';
314 : else
315 0 : *p++ = *s;
316 : }
317 0 : *p = 0;
318 0 : free (name);
319 :
320 :
321 0 : err = gpgsm_agent_get_confirmation (ctrl, buffer);
322 :
323 0 : xfree (buffer);
324 0 : return err;
325 : }
|