* protect.c (do_encryption): Use gcry_create_nonce instad of the
[gnupg.git] / agent / trustlist.c
1 /* trustlist.c - Maintain the list of trusted keys
2  *      Copyright (C) 2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <assert.h>
28 #include <unistd.h>
29 #include <sys/stat.h>
30
31 #include "agent.h"
32 #include <assuan.h> /* fixme: need a way to avoid assuan calls here */
33
34 static const char headerblurb[] =
35 "# This is the list of trusted keys.  Comments like this one and empty\n"
36 "# lines are allowed but keep in mind that the entire file is integrity\n"
37 "# protected by the use of a MAC, so changing the file does not make\n"
38 "# much sense without the knowledge of the MAC key.  Lines do have a\n"
39 "# length limit but this is not serious limitation as the format of the\n"
40 "# entries is fixed and checked by gpg-agent: A non-comment line starts\n"
41 "# with optional white spaces, followed by exactly 40 hex character,\n"
42 "# optioanlly followed by a flag character which my either be 'P', 'S'\n"
43 "# or '*'. Additional data delimited with by a white space is ignored.\n"
44 "\n";
45
46
47 static FILE *trustfp;
48
49
50 static int
51 open_list (int append)
52 {
53   char *fname;
54
55   fname = make_filename (opt.homedir, "trustlist.txt", NULL);
56   trustfp = fopen (fname, append? "a+":"r");
57   if (!trustfp && errno == ENOENT)
58     {
59       trustfp = fopen (fname, "wx");
60       if (!trustfp)
61         {
62           gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
63           log_error ("can't create `%s': %s\n", fname, strerror (errno));
64           xfree (fname);
65           return tmperr;
66         }
67       fputs (headerblurb, trustfp);
68       fclose (trustfp);
69       trustfp = fopen (fname, append? "a+":"r");
70     }
71
72   if (!trustfp)
73     {
74       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
75       log_error ("can't open `%s': %s\n", fname, strerror (errno));
76       xfree (fname);
77       return tmperr;
78     }
79
80   /*FIXME: check the MAC */
81
82   return 0;
83 }
84
85
86
87 /* Read the trustlist and return entry by entry.  KEY must point to a
88    buffer of at least 41 characters. KEYFLAG does return either 'P',
89    'S' or '*'.
90
91    Reading a valid entry return 0, EOF returns -1 any other error
92    returns the appropriate error code. */
93 static int
94 read_list (char *key, int *keyflag)
95 {
96   int rc;
97   int c, i;
98   char *p, line[256];
99   
100   if (!trustfp)
101     {
102       rc = open_list (0);
103       if (rc)
104         return rc;
105     }
106
107   do
108     {
109       if (!fgets (line, DIM(line)-1, trustfp) )
110         {
111           if (feof (trustfp))
112             return -1;
113           return gpg_error (gpg_err_code_from_errno (errno));
114         }
115       
116       if (!*line || line[strlen(line)-1] != '\n')
117         {
118           /* eat until end of line */
119           while ( (c=getc (trustfp)) != EOF && c != '\n')
120             ;
121           return gpg_error (*line? GPG_ERR_LINE_TOO_LONG
122                                  : GPG_ERR_INCOMPLETE_LINE);
123         }
124       
125       /* Allow for emty lines and spaces */
126       for (p=line; spacep (p); p++)
127         ;
128     }
129   while (!*p || *p == '\n' || *p == '#');
130   
131   for (i=0; hexdigitp (p+i) && i < 40; i++)
132     key[i] = p[i] >= 'a'? (p[i] & 0xdf): p[i];
133   key[i] = 0;
134   if (i!=40 || !(spacep (p+i) || p[i] == '\n'))
135     {
136       log_error ("invalid formatted fingerprint in trustlist\n");
137       return gpg_error (GPG_ERR_BAD_DATA);
138     }
139   assert (p[i]);
140   if (p[i] == '\n')
141     *keyflag = '*';
142   else 
143     {
144       i++;
145       if ( p[i] == 'P' || p[i] == 'p')
146         *keyflag = 'P';
147       else if ( p[i] == 'S' || p[i] == 's')
148         *keyflag = 'S';
149       else if ( p[i] == '*')
150         *keyflag = '*';
151       else
152         {
153           log_error ("invalid keyflag in trustlist\n");
154           return gpg_error (GPG_ERR_BAD_DATA);
155         }
156       i++;
157       if ( !(spacep (p+i) || p[i] == '\n'))
158         {
159           log_error ("invalid keyflag in trustlist\n");
160           return gpg_error (GPG_ERR_BAD_DATA);
161         }
162     }
163
164   return 0;
165 }
166
167 /* check whether the given fpr is in our trustdb.  We expect FPR to be
168    an all uppercase hexstring of 40 characters. */
169 int 
170 agent_istrusted (const char *fpr)
171 {
172   int rc;
173   static char key[41];
174   int keyflag;
175
176   if (trustfp)
177     rewind (trustfp);
178   while (!(rc=read_list (key, &keyflag)))
179     {
180       if (!strcmp (key, fpr))
181         return 0;
182     }
183   if (rc != -1)
184     {
185       /* error in the trustdb - close it to give the user a chance for
186          correction */
187       fclose (trustfp);
188       trustfp = NULL;
189     }
190   return rc;
191 }
192
193
194 /* write all trust entries to FP */
195 int 
196 agent_listtrusted (void *assuan_context)
197 {
198   int rc;
199   static char key[51];
200   int keyflag;
201
202   if (trustfp)
203     rewind (trustfp);
204   while (!(rc=read_list (key, &keyflag)))
205     {
206       key[40] = ' ';
207       key[41] = keyflag;
208       key[42] = '\n';
209       assuan_send_data (assuan_context, key, 43);
210       assuan_send_data (assuan_context, NULL, 0); /* flush */
211     } 
212   if (rc == -1)
213     rc = 0;
214   if (rc)
215     {
216       /* error in the trustdb - close it to give the user a chance for
217          correction */
218       fclose (trustfp);
219       trustfp = NULL;
220     }
221   return rc;
222 }
223
224
225 /* Insert the given fpr into our trustdb.  We expect FPR to be an all
226    uppercase hexstring of 40 characters. FLAG is either 'P' or 'C'.
227    This function does first check whether that key has alreay ben put
228    into the trustdb and returns success in this case.  Before a FPR
229    actually gets inserted, the user is asked by means of the pin-entry
230    whether this is actual wants he want to do.
231 */
232 int 
233 agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag)
234 {
235   int rc;
236   static char key[41];
237   int keyflag;
238   char *desc;
239
240   if (trustfp)
241     rewind (trustfp);
242   while (!(rc=read_list (key, &keyflag)))
243     {
244       if (!strcmp (key, fpr))
245         return 0;
246     }
247   fclose (trustfp);
248   trustfp = NULL;
249   if (rc != -1)
250     return rc;   /* error in the trustdb */
251
252   /* insert a new one */
253   if (asprintf (&desc,
254                 "Please verify that the certificate identified as:%%0A"
255                 "  \"%s\"%%0A"
256                 "has the fingerprint:%%0A"
257                 "  %s", name, fpr) < 0 )
258     return out_of_core ();
259   rc = agent_get_confirmation (ctrl, desc, "Correct", "No");
260   free (desc);
261   if (rc)
262     return rc;
263
264   if (asprintf (&desc,
265                 "Do you ultimately trust%%0A"
266                 "  \"%s\"%%0A"
267                 "to correctly certify user certificates?",
268                 name) < 0 )
269     return out_of_core ();
270   rc = agent_get_confirmation (ctrl, desc, "Yes", "No");
271   free (desc);
272   if (rc)
273     return rc;
274
275   /* now check again to avoid duplicates.  Also open in append mode now */
276   rc = open_list (1);
277   if (rc)
278     return rc;
279   rewind (trustfp);
280   while (!(rc=read_list (key, &keyflag)))
281     {
282       if (!strcmp (key, fpr))
283         return 0;
284     }
285   if (rc != -1)
286     {
287       fclose (trustfp);
288       trustfp = NULL;
289       return rc;   /* error in the trustdb */
290     }
291   rc = 0;
292
293   /* append the key */
294   fflush (trustfp);
295   fputs ("\n# ", trustfp);
296   print_sanitized_string (trustfp, name, 0);
297   fprintf (trustfp, "\n%s %c\n", fpr, flag);
298   if (ferror (trustfp))
299     rc = gpg_error (gpg_err_code_from_errno (errno));
300   
301   /* close because we are in append mode */
302   if (fclose (trustfp))
303     rc = gpg_error (gpg_err_code_from_errno (errno));
304   trustfp = NULL;
305   return rc;
306 }