VArious hacks to make it at least build under W32.
[gnupg.git] / agent / findkey.c
1 /* findkey.c - locate the secret key
2  * Copyright (C) 2001, 2002, 2003, 2004 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 <fcntl.h>
28 #include <assert.h>
29 #include <unistd.h>
30 #include <sys/stat.h>
31 #include <assert.h>
32
33 #include "agent.h"
34
35 /* Helper to pass data to the check callback of the unprotect function. */
36 struct try_unprotect_arg_s {
37   const unsigned char *protected_key;
38   unsigned char *unprotected_key;
39 };
40
41
42
43 int
44 agent_write_private_key (const unsigned char *grip,
45                          const void *buffer, size_t length, int force)
46 {
47   int i;
48   char *fname;
49   FILE *fp;
50   char hexgrip[40+4+1];
51   
52   for (i=0; i < 20; i++)
53     sprintf (hexgrip+2*i, "%02X", grip[i]);
54   strcpy (hexgrip+40, ".key");
55
56   fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
57   if (force)
58     fp = fopen (fname, "wb");
59   else
60     {
61       int fd;
62
63       if (!access (fname, F_OK))
64       {
65         log_error ("secret key file `%s' already exists\n", fname);
66         xfree (fname);
67         return gpg_error (GPG_ERR_GENERAL);
68       }
69
70       /* We would like to create FNAME but only if it does not already
71          exist.  We cannot make this guarantee just using POSIX (GNU
72          provides the "x" opentype for fopen, however, this is not
73          portable).  Thus, we use the more flexible open function and
74          then use fdopen to obtain a stream.
75
76          The mode parameter to open is what fopen uses.  It will be
77          combined with the process' umask automatically.  */
78       fd = open (fname, O_CREAT | O_EXCL | O_RDWR,
79                  S_IRUSR | S_IWUSR 
80 #ifndef HAVE_W32_SYSTEM
81                  | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
82 #endif
83                  );
84       if (fd < 0)
85         fp = 0;
86       else
87         {
88           fp = fdopen (fd, "wb");
89           if (!fp)
90             { 
91               int save_e = errno;
92               close (fd);
93               errno = save_e;
94             }
95         }
96     }
97
98   if (!fp) 
99     { 
100       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
101       log_error ("can't create `%s': %s\n", fname, strerror (errno));
102       xfree (fname);
103       return tmperr;
104     }
105
106   if (fwrite (buffer, length, 1, fp) != 1)
107     {
108       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
109       log_error ("error writing `%s': %s\n", fname, strerror (errno));
110       fclose (fp);
111       remove (fname);
112       xfree (fname);
113       return tmperr;
114     }
115   if ( fclose (fp) )
116     {
117       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
118       log_error ("error closing `%s': %s\n", fname, strerror (errno));
119       remove (fname);
120       xfree (fname);
121       return tmperr;
122     }
123
124   xfree (fname);
125   return 0;
126 }
127
128
129 /* Callback function to try the unprotection from the passpharse query
130    code. */
131 static int
132 try_unprotect_cb (struct pin_entry_info_s *pi)
133 {
134   struct try_unprotect_arg_s *arg = pi->check_cb_arg;
135   size_t dummy;
136
137   assert (!arg->unprotected_key);
138   return agent_unprotect (arg->protected_key, pi->pin,
139                           &arg->unprotected_key, &dummy);
140 }
141
142
143 /* Unprotect the canconical encoded S-expression key in KEYBUF.  GRIP
144    should be the hex encoded keygrip of that key to be used with the
145    caching mechanism. DESC_TEXT may be set to override the default
146    description used for the pinentry. */
147 static int
148 unprotect (CTRL ctrl, const char *desc_text,
149            unsigned char **keybuf, const unsigned char *grip, int ignore_cache)
150 {
151   struct pin_entry_info_s *pi;
152   struct try_unprotect_arg_s arg;
153   int rc, i;
154   unsigned char *result;
155   size_t resultlen;
156   char hexgrip[40+1];
157   
158   for (i=0; i < 20; i++)
159     sprintf (hexgrip+2*i, "%02X", grip[i]);
160   hexgrip[40] = 0;
161
162   /* First try to get it from the cache - if there is none or we can't
163      unprotect it, we fall back to ask the user */
164   if (!ignore_cache)
165     {
166       void *cache_marker;
167       const char *pw = agent_get_cache (hexgrip, &cache_marker);
168       if (pw)
169         {
170           rc = agent_unprotect (*keybuf, pw, &result, &resultlen);
171           agent_unlock_cache_entry (&cache_marker);
172           if (!rc)
173             {
174               xfree (*keybuf);
175               *keybuf = result;
176               return 0;
177             }
178           rc  = 0;
179         }
180     }
181   
182   pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
183   pi->max_length = 100;
184   pi->min_digits = 0;  /* we want a real passphrase */
185   pi->max_digits = 8;
186   pi->max_tries = 3;
187   pi->check_cb = try_unprotect_cb;
188   arg.protected_key = *keybuf;
189   arg.unprotected_key = NULL;
190   pi->check_cb_arg = &arg;
191
192   rc = agent_askpin (ctrl, desc_text, NULL, pi);
193   if (!rc)
194     {
195       assert (arg.unprotected_key);
196       agent_put_cache (hexgrip, pi->pin, 0);
197       xfree (*keybuf);
198       *keybuf = arg.unprotected_key;
199     }
200   xfree (pi);
201   return rc;
202 }
203
204
205
206 /* Return the secret key as an S-Exp in RESULT after locating it using
207    the grip.  Returns NULL in RESULT if the operation should be
208    diverted to a token; SHADOW_INFO will point then to an allocated
209    S-Expression with the shadow_info part from the file.  With
210    IGNORE_CACHE passed as true the passphrase is not taken from the
211    cache.  DESC_TEXT may be set to present a custom description for the
212    pinentry. */
213 gpg_error_t
214 agent_key_from_file (CTRL ctrl, const char *desc_text,
215                      const unsigned char *grip, unsigned char **shadow_info,
216                      int ignore_cache, gcry_sexp_t *result)
217 {
218   int i, rc;
219   char *fname;
220   FILE *fp;
221   struct stat st;
222   unsigned char *buf;
223   size_t len, buflen, erroff;
224   gcry_sexp_t s_skey;
225   char hexgrip[40+4+1];
226   int got_shadow_info = 0;
227   
228   *result = NULL;
229   if (shadow_info)
230       *shadow_info = NULL;
231
232   for (i=0; i < 20; i++)
233     sprintf (hexgrip+2*i, "%02X", grip[i]);
234   strcpy (hexgrip+40, ".key");
235
236   fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
237   fp = fopen (fname, "rb");
238   if (!fp)
239     {
240       rc = gpg_error_from_errno (errno);
241       log_error ("can't open `%s': %s\n", fname, strerror (errno));
242       xfree (fname);
243       return rc;
244     }
245   
246   if (fstat (fileno(fp), &st))
247     {
248       rc = gpg_error_from_errno (errno);
249       log_error ("can't stat `%s': %s\n", fname, strerror (errno));
250       xfree (fname);
251       fclose (fp);
252       return rc;
253     }
254
255   buflen = st.st_size;
256   buf = xmalloc (buflen+1);
257   if (fread (buf, buflen, 1, fp) != 1)
258     {
259       rc = gpg_error_from_errno (errno);
260       log_error ("error reading `%s': %s\n", fname, strerror (errno));
261       xfree (fname);
262       fclose (fp);
263       xfree (buf);
264       return rc;
265     }
266
267   rc = gcry_sexp_sscan (&s_skey, &erroff, buf, buflen);
268   xfree (fname);
269   fclose (fp);
270   xfree (buf);
271   if (rc)
272     {
273       log_error ("failed to build S-Exp (off=%u): %s\n",
274                  (unsigned int)erroff, gpg_strerror (rc));
275       return rc;
276     }
277   len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, NULL, 0);
278   assert (len);
279   buf = xtrymalloc (len);
280   if (!buf)
281     {
282       rc = out_of_core ();
283       gcry_sexp_release (s_skey);
284       return rc;
285     }
286   len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, buf, len);
287   assert (len);
288   gcry_sexp_release (s_skey);
289
290   switch (agent_private_key_type (buf))
291     {
292     case PRIVATE_KEY_CLEAR:
293       break; /* no unprotection needed */
294     case PRIVATE_KEY_PROTECTED:
295       rc = unprotect (ctrl, desc_text, &buf, grip, ignore_cache);
296       if (rc)
297         log_error ("failed to unprotect the secret key: %s\n",
298                    gpg_strerror (rc));
299       break;
300     case PRIVATE_KEY_SHADOWED:
301       if (shadow_info)
302         {
303           const unsigned char *s;
304           size_t n;
305
306           rc = agent_get_shadow_info (buf, &s);
307           if (!rc)
308             {
309               n = gcry_sexp_canon_len (s, 0, NULL,NULL);
310               assert (n);
311               *shadow_info = xtrymalloc (n);
312               if (!*shadow_info)
313                 rc = out_of_core ();
314               else
315                 {
316                   memcpy (*shadow_info, s, n);
317                   rc = 0;
318                   got_shadow_info = 1;
319                 }
320             }
321           if (rc)
322             log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
323         }
324       else
325         rc = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
326       break;
327     default:
328       log_error ("invalid private key format\n");
329       rc = gpg_error (GPG_ERR_BAD_SECKEY);
330       break;
331     }
332   if (rc || got_shadow_info)
333     {
334       xfree (buf);
335       return rc;
336     }
337
338   buflen = gcry_sexp_canon_len (buf, 0, NULL, NULL);
339   rc = gcry_sexp_sscan (&s_skey, &erroff, buf, buflen);
340   wipememory (buf, buflen);
341   xfree (buf);
342   if (rc)
343     {
344       log_error ("failed to build S-Exp (off=%u): %s\n",
345                  (unsigned int)erroff, gpg_strerror (rc));
346       return rc;
347     }
348
349   *result = s_skey;
350   return 0;
351 }
352
353 /* Return the secret key as an S-Exp after locating it using the grip.
354    Returns NULL if key is not available. 0 = key is available */
355 int
356 agent_key_available (const unsigned char *grip)
357 {
358   int i;
359   char *fname;
360   char hexgrip[40+4+1];
361   
362   for (i=0; i < 20; i++)
363     sprintf (hexgrip+2*i, "%02X", grip[i]);
364   strcpy (hexgrip+40, ".key");
365
366   fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
367   i = !access (fname, R_OK)? 0 : -1;
368   xfree (fname);
369   return i;
370 }
371
372
373