gpg: Make sure we only have a single SQL statement.
[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
36
37 /* Return true if Libgcrypt's RNG is in faked mode.  */
38 int
39 random_is_faked (void)
40 {
41   return !!gcry_control (GCRYCTL_FAKED_RANDOM_P, 0);
42 }
43
44
45 void
46 release_sk_list (SK_LIST sk_list)
47 {
48   SK_LIST sk_rover;
49
50   for (; sk_list; sk_list = sk_rover)
51     {
52       sk_rover = sk_list->next;
53       free_public_key (sk_list->pk);
54       xfree (sk_list);
55     }
56 }
57
58
59 /* Check that we are only using keys which don't have
60  * the string "(insecure!)" or "not secure" or "do not use"
61  * in one of the user ids.  */
62 static int
63 is_insecure (PKT_public_key *pk)
64 {
65   u32 keyid[2];
66   KBNODE node = NULL, u;
67   int insecure = 0;
68
69   keyid_from_pk (pk, keyid);
70   node = get_pubkeyblock (keyid);
71   for (u = node; u; u = u->next)
72     {
73       if (u->pkt->pkttype == PKT_USER_ID)
74         {
75           PKT_user_id *id = u->pkt->pkt.user_id;
76           if (id->attrib_data)
77             continue;           /* skip attribute packets */
78           if (strstr (id->name, "(insecure!)")
79               || strstr (id->name, "not secure")
80               || strstr (id->name, "do not use")
81               || strstr (id->name, "(INSECURE!)"))
82             {
83               insecure = 1;
84               break;
85             }
86         }
87     }
88   release_kbnode (node);
89
90   return insecure;
91 }
92
93 static int
94 key_present_in_sk_list (SK_LIST sk_list, PKT_public_key *pk)
95 {
96   for (; sk_list; sk_list = sk_list->next)
97     {
98       if (!cmp_public_keys (sk_list->pk, pk))
99         return 0;
100     }
101   return -1;
102 }
103
104 static int
105 is_duplicated_entry (strlist_t list, strlist_t item)
106 {
107   for (; list && list != item; list = list->next)
108     {
109       if (!strcmp (list->d, item->d))
110         return 1;
111     }
112   return 0;
113 }
114
115
116 gpg_error_t
117 build_sk_list (strlist_t locusr, SK_LIST *ret_sk_list, unsigned int use)
118 {
119   gpg_error_t err;
120   SK_LIST sk_list = NULL;
121
122   if (!locusr) /* No user ids given - use the default key.  */
123     {
124       PKT_public_key *pk;
125
126       pk = xmalloc_clear (sizeof *pk);
127       pk->req_usage = use;
128       if ((err = getkey_byname (NULL, pk, NULL, 1, NULL)))
129         {
130           free_public_key (pk);
131           pk = NULL;
132           log_error ("no default secret key: %s\n", gpg_strerror (err));
133           write_status_text (STATUS_INV_SGNR, get_inv_recpsgnr_code (err));
134         }
135       else if ((err = openpgp_pk_test_algo2 (pk->pubkey_algo, use)))
136         {
137           free_public_key (pk);
138           pk = NULL;
139           log_error ("invalid default secret key: %s\n", gpg_strerror (err));
140           write_status_text (STATUS_INV_SGNR, get_inv_recpsgnr_code (err));
141         }
142       else
143         {
144           SK_LIST r;
145
146           if (random_is_faked () && !is_insecure (pk))
147             {
148               log_info (_("key is not flagged as insecure - "
149                           "can't use it with the faked RNG!\n"));
150               free_public_key (pk);
151               pk = NULL;
152               write_status_text (STATUS_INV_SGNR,
153                                  get_inv_recpsgnr_code (GPG_ERR_NOT_TRUSTED));
154             }
155           else
156             {
157               r = xmalloc (sizeof *r);
158               r->pk = pk;
159               pk = NULL;
160               r->next = sk_list;
161               r->mark = 0;
162               sk_list = r;
163             }
164         }
165     }
166   else /* Check the given user ids.  */
167     {
168       strlist_t locusr_orig = locusr;
169
170       for (; locusr; locusr = locusr->next)
171         {
172           PKT_public_key *pk;
173
174           err = 0;
175           /* Do an early check against duplicated entries.  However
176            * this won't catch all duplicates because the user IDs may
177            * be specified in different ways.  */
178           if (is_duplicated_entry (locusr_orig, locusr))
179             {
180               log_info (_("skipped \"%s\": duplicated\n"), locusr->d);
181               continue;
182             }
183           pk = xmalloc_clear (sizeof *pk);
184           pk->req_usage = use;
185           if ((err = getkey_byname (NULL, pk, locusr->d, 1, NULL)))
186             {
187               free_public_key (pk);
188               pk = NULL;
189               log_error (_("skipped \"%s\": %s\n"),
190                          locusr->d, gpg_strerror (err));
191               write_status_text_and_buffer
192                 (STATUS_INV_SGNR, get_inv_recpsgnr_code (err),
193                  locusr->d, strlen (locusr->d), -1);
194             }
195           else if (!key_present_in_sk_list (sk_list, pk))
196             {
197               free_public_key (pk);
198               pk = NULL;
199               log_info (_("skipped: secret key already present\n"));
200             }
201           else if ((err = openpgp_pk_test_algo2 (pk->pubkey_algo, use)))
202             {
203               free_public_key (pk);
204               pk = NULL;
205               log_error ("skipped \"%s\": %s\n", locusr->d, gpg_strerror (err));
206               write_status_text_and_buffer
207                 (STATUS_INV_SGNR, get_inv_recpsgnr_code (err),
208                  locusr->d, strlen (locusr->d), -1);
209             }
210           else
211             {
212               SK_LIST r;
213
214               if (pk->version == 4 && (use & PUBKEY_USAGE_SIG)
215                   && pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E)
216                 {
217                   log_info (_("skipped \"%s\": %s\n"), locusr->d,
218                             _("this is a PGP generated Elgamal key which"
219                               " is not secure for signatures!"));
220                   free_public_key (pk);
221                   pk = NULL;
222                   write_status_text_and_buffer
223                     (STATUS_INV_SGNR,
224                      get_inv_recpsgnr_code (GPG_ERR_WRONG_KEY_USAGE),
225                      locusr->d, strlen (locusr->d), -1);
226                 }
227               else if (random_is_faked () && !is_insecure (pk))
228                 {
229                   log_info (_("key is not flagged as insecure - "
230                               "can't use it with the faked RNG!\n"));
231                   free_public_key (pk);
232                   pk = NULL;
233                   write_status_text_and_buffer
234                     (STATUS_INV_SGNR,
235                      get_inv_recpsgnr_code (GPG_ERR_NOT_TRUSTED),
236                      locusr->d, strlen (locusr->d), -1);
237                 }
238               else
239                 {
240                   r = xmalloc (sizeof *r);
241                   r->pk = pk;
242                   pk = NULL;
243                   r->next = sk_list;
244                   r->mark = 0;
245                   sk_list = r;
246                 }
247             }
248         }
249     }
250
251   if (!err && !sk_list)
252     {
253       log_error ("no valid signators\n");
254       write_status_text (STATUS_NO_SGNR, "0");
255       err = gpg_error (GPG_ERR_NO_USER_ID);
256     }
257
258   if (err)
259     release_sk_list (sk_list);
260   else
261     *ret_sk_list = sk_list;
262   return err;
263 }