Decryption and signi via agent is now implemented.
[gnupg.git] / g10 / skclist.c
1 /* skclist.c - Build a list of secret keys
2  * Copyright (C) 1998, 1999, 2000, 2001, 2006,
3  *               2010 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27
28 #include "gpg.h"
29 #include "options.h"
30 #include "packet.h"
31 #include "status.h"
32 #include "keydb.h"
33 #include "util.h"
34 #include "i18n.h"
35 #include "cipher.h"
36
37
38 /* Return true if Libgcrypt's RNG is in faked mode.  */
39 int
40 random_is_faked (void)
41 {
42   return !!gcry_control (GCRYCTL_FAKED_RANDOM_P, 0);
43 }
44
45
46 void
47 release_sk_list (SK_LIST sk_list)
48 {
49   SK_LIST sk_rover;
50
51   for (; sk_list; sk_list = sk_rover)
52     {
53       sk_rover = sk_list->next;
54       if (sk_list->pk)
55         free_public_key (sk_list->pk);
56       xfree (sk_list);
57     }
58 }
59
60
61 /* Check that we are only using keys which don't have
62  * the string "(insecure!)" or "not secure" or "do not use"
63  * in one of the user ids.  */
64 static int
65 is_insecure (PKT_public_key *pk)
66 {
67   u32 keyid[2];
68   KBNODE node = NULL, u;
69   int insecure = 0;
70
71   keyid_from_pk (pk, keyid);
72   node = get_pubkeyblock (keyid);
73   for (u = node; u; u = u->next)
74     {
75       if (u->pkt->pkttype == PKT_USER_ID)
76         {
77           PKT_user_id *id = u->pkt->pkt.user_id;
78           if (id->attrib_data)
79             continue;           /* skip attribute packets */
80           if (strstr (id->name, "(insecure!)")
81               || strstr (id->name, "not secure")
82               || strstr (id->name, "do not use")
83               || strstr (id->name, "(INSECURE!)"))
84             {
85               insecure = 1;
86               break;
87             }
88         }
89     }
90   release_kbnode (node);
91
92   return insecure;
93 }
94
95 static int
96 key_present_in_sk_list (SK_LIST sk_list, PKT_public_key *pk)
97 {
98   for (; sk_list; sk_list = sk_list->next)
99     {
100       if (!cmp_public_keys (sk_list->pk, pk))
101         return 0;
102     }
103   return -1;
104 }
105
106 static int
107 is_duplicated_entry (strlist_t list, strlist_t item)
108 {
109   for (; list && list != item; list = list->next)
110     {
111       if (!strcmp (list->d, item->d))
112         return 1;
113     }
114   return 0;
115 }
116
117
118 gpg_error_t
119 build_sk_list (strlist_t locusr, SK_LIST *ret_sk_list, unsigned int use)
120 {
121   gpg_error_t err;
122   SK_LIST sk_list = NULL;
123
124   if (!locusr) /* No user ids given - use the default key.  */
125     {
126       PKT_public_key *pk;
127
128       pk = xmalloc_clear (sizeof *pk);
129       pk->req_usage = use;
130       if ((err = getkey_byname (NULL, pk, NULL, 1, NULL)))
131         {
132           free_public_key (pk);
133           pk = NULL;
134           log_error ("no default secret key: %s\n", gpg_strerror (err));
135           write_status_text (STATUS_INV_SGNR, get_inv_recpsgnr_code (err));
136         }
137       else if ((err = openpgp_pk_test_algo2 (pk->pubkey_algo, use)))
138         {
139           free_public_key (pk);
140           pk = NULL;
141           log_error ("invalid default secret key: %s\n", gpg_strerror (err));
142           write_status_text (STATUS_INV_SGNR, get_inv_recpsgnr_code (err));
143         }
144       else
145         {
146           SK_LIST r;
147           
148           if (random_is_faked () && !is_insecure (pk))
149             {
150               log_info (_("key is not flagged as insecure - "
151                           "can't use it with the faked RNG!\n"));
152               free_public_key (pk);
153               pk = NULL;
154               write_status_text (STATUS_INV_SGNR,
155                                  get_inv_recpsgnr_code (GPG_ERR_NOT_TRUSTED));
156             }
157           else
158             {
159               r = xmalloc (sizeof *r);
160               r->pk = pk;
161               pk = NULL;
162               r->next = sk_list;
163               r->mark = 0;
164               sk_list = r;
165             }
166         }
167     }
168   else /* Check the given user ids.  */
169     {
170       strlist_t locusr_orig = locusr;
171
172       for (; locusr; locusr = locusr->next)
173         {
174           PKT_public_key *pk;
175
176           err = 0;
177           /* Do an early check against duplicated entries.  However
178            * this won't catch all duplicates because the user IDs may
179            * be specified in different ways.  */
180           if (is_duplicated_entry (locusr_orig, locusr))
181             {
182               log_info (_("skipped \"%s\": duplicated\n"), locusr->d);
183               continue;
184             }
185           pk = xmalloc_clear (sizeof *pk);
186           pk->req_usage = use;
187           if ((err = getkey_byname (NULL, pk, locusr->d, 1, NULL)))
188             {
189               free_public_key (pk);
190               pk = NULL;
191               log_error (_("skipped \"%s\": %s\n"),
192                          locusr->d, gpg_strerror (err));
193               write_status_text_and_buffer
194                 (STATUS_INV_SGNR, get_inv_recpsgnr_code (err),
195                  locusr->d, strlen (locusr->d), -1);
196             }
197           else if (!key_present_in_sk_list (sk_list, pk))
198             {
199               free_public_key (pk);
200               pk = NULL;
201               log_info (_("skipped: secret key already present\n"));
202             }
203           else if ((err = openpgp_pk_test_algo2 (pk->pubkey_algo, use)))
204             {
205               free_public_key (pk);
206               pk = NULL;
207               log_error ("skipped \"%s\": %s\n", locusr->d, gpg_strerror (err));
208               write_status_text_and_buffer
209                 (STATUS_INV_SGNR, get_inv_recpsgnr_code (err),
210                  locusr->d, strlen (locusr->d), -1);
211             }
212           else
213             {
214               SK_LIST r;
215               
216               if (pk->version == 4 && (use & PUBKEY_USAGE_SIG)
217                   && pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E)
218                 {
219                   log_info (_("skipped \"%s\": %s\n"), locusr->d,
220                             _("this is a PGP generated Elgamal key which"
221                               " is not secure for signatures!"));
222                   free_public_key (pk);
223                   pk = NULL;
224                   write_status_text_and_buffer
225                     (STATUS_INV_SGNR,
226                      get_inv_recpsgnr_code (GPG_ERR_WRONG_KEY_USAGE),
227                      locusr->d, strlen (locusr->d), -1);
228                 }
229               else if (random_is_faked () && !is_insecure (pk))
230                 {
231                   log_info (_("key is not flagged as insecure - "
232                               "can't use it with the faked RNG!\n"));
233                   free_public_key (pk);
234                   pk = NULL;
235                   write_status_text_and_buffer
236                     (STATUS_INV_SGNR,
237                      get_inv_recpsgnr_code (GPG_ERR_NOT_TRUSTED),
238                      locusr->d, strlen (locusr->d), -1);
239                 }
240               else
241                 {
242                   r = xmalloc (sizeof *r);
243                   r->pk = pk;
244                   pk = NULL;
245                   r->next = sk_list;
246                   r->mark = 0;
247                   sk_list = r;
248                 }
249             }
250         }
251     }
252
253   if (!err && !sk_list)
254     {
255       log_error ("no valid signators\n");
256       write_status_text (STATUS_NO_SGNR, "0");
257       err = gpg_error (GPG_ERR_NO_USER_ID);
258     }
259   
260   if (err)
261     release_sk_list (sk_list);
262   else
263     *ret_sk_list = sk_list;
264   return err;
265 }