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