dirmngr: Change the Onion keyserver in the conf template.
[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 (ctrl_t ctrl,
118                strlist_t locusr, SK_LIST *ret_sk_list, unsigned int use)
119 {
120   gpg_error_t err;
121   SK_LIST sk_list = NULL;
122
123   /* XXX: Change this function to use get_pubkeys instead of
124      getkey_byname to detect ambiguous key specifications and warn
125      about duplicate keyblocks.  For ambiguous key specifications on
126      the command line or provided interactively, prompt the user to
127      select the best key.  If a key specification is ambiguous and we
128      are in batch mode, die.  */
129
130   if (!locusr) /* No user ids given - use the default key.  */
131     {
132       PKT_public_key *pk;
133
134       pk = xmalloc_clear (sizeof *pk);
135       pk->req_usage = use;
136       if ((err = getkey_byname (ctrl, NULL, pk, NULL, 1, NULL)))
137         {
138           free_public_key (pk);
139           pk = NULL;
140           log_error ("no default secret key: %s\n", gpg_strerror (err));
141           write_status_text (STATUS_INV_SGNR, get_inv_recpsgnr_code (err));
142         }
143       else if ((err = openpgp_pk_test_algo2 (pk->pubkey_algo, use)))
144         {
145           free_public_key (pk);
146           pk = NULL;
147           log_error ("invalid default secret key: %s\n", gpg_strerror (err));
148           write_status_text (STATUS_INV_SGNR, get_inv_recpsgnr_code (err));
149         }
150       else
151         {
152           SK_LIST r;
153
154           if (random_is_faked () && !is_insecure (pk))
155             {
156               log_info (_("key is not flagged as insecure - "
157                           "can't use it with the faked RNG!\n"));
158               free_public_key (pk);
159               pk = NULL;
160               write_status_text (STATUS_INV_SGNR,
161                                  get_inv_recpsgnr_code (GPG_ERR_NOT_TRUSTED));
162             }
163           else
164             {
165               r = xmalloc (sizeof *r);
166               r->pk = pk;
167               pk = NULL;
168               r->next = sk_list;
169               r->mark = 0;
170               sk_list = r;
171             }
172         }
173     }
174   else /* Check the given user ids.  */
175     {
176       strlist_t locusr_orig = locusr;
177
178       for (; locusr; locusr = locusr->next)
179         {
180           PKT_public_key *pk;
181
182           err = 0;
183           /* Do an early check against duplicated entries.  However
184            * this won't catch all duplicates because the user IDs may
185            * be specified in different ways.  */
186           if (is_duplicated_entry (locusr_orig, locusr))
187             {
188               log_info (_("skipped \"%s\": duplicated\n"), locusr->d);
189               continue;
190             }
191           pk = xmalloc_clear (sizeof *pk);
192           pk->req_usage = use;
193           if ((err = getkey_byname (ctrl, NULL, pk, locusr->d, 1, NULL)))
194             {
195               free_public_key (pk);
196               pk = NULL;
197               log_error (_("skipped \"%s\": %s\n"),
198                          locusr->d, gpg_strerror (err));
199               write_status_text_and_buffer
200                 (STATUS_INV_SGNR, get_inv_recpsgnr_code (err),
201                  locusr->d, strlen (locusr->d), -1);
202             }
203           else if (!key_present_in_sk_list (sk_list, pk))
204             {
205               free_public_key (pk);
206               pk = NULL;
207               log_info (_("skipped: secret key already present\n"));
208             }
209           else if ((err = openpgp_pk_test_algo2 (pk->pubkey_algo, use)))
210             {
211               free_public_key (pk);
212               pk = NULL;
213               log_error ("skipped \"%s\": %s\n", locusr->d, gpg_strerror (err));
214               write_status_text_and_buffer
215                 (STATUS_INV_SGNR, get_inv_recpsgnr_code (err),
216                  locusr->d, strlen (locusr->d), -1);
217             }
218           else
219             {
220               SK_LIST r;
221
222               if (pk->version == 4 && (use & PUBKEY_USAGE_SIG)
223                   && pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E)
224                 {
225                   log_info (_("skipped \"%s\": %s\n"), locusr->d,
226                             _("this is a PGP generated Elgamal key which"
227                               " is not secure for signatures!"));
228                   free_public_key (pk);
229                   pk = NULL;
230                   write_status_text_and_buffer
231                     (STATUS_INV_SGNR,
232                      get_inv_recpsgnr_code (GPG_ERR_WRONG_KEY_USAGE),
233                      locusr->d, strlen (locusr->d), -1);
234                 }
235               else if (random_is_faked () && !is_insecure (pk))
236                 {
237                   log_info (_("key is not flagged as insecure - "
238                               "can't use it with the faked RNG!\n"));
239                   free_public_key (pk);
240                   pk = NULL;
241                   write_status_text_and_buffer
242                     (STATUS_INV_SGNR,
243                      get_inv_recpsgnr_code (GPG_ERR_NOT_TRUSTED),
244                      locusr->d, strlen (locusr->d), -1);
245                 }
246               else
247                 {
248                   r = xmalloc (sizeof *r);
249                   r->pk = pk;
250                   pk = NULL;
251                   r->next = sk_list;
252                   r->mark = 0;
253                   sk_list = r;
254                 }
255             }
256         }
257     }
258
259   if (!err && !sk_list)
260     {
261       log_error ("no valid signators\n");
262       write_status_text (STATUS_NO_SGNR, "0");
263       err = gpg_error (GPG_ERR_NO_USER_ID);
264     }
265
266   if (err)
267     release_sk_list (sk_list);
268   else
269     *ret_sk_list = sk_list;
270   return err;
271 }