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