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