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