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