Moved 1.9 branch to trunk
[gnupg.git] / g10 / skclist.c
1 /* skclist.c - Build a list of secret keys
2  * Copyright (C) 1998, 1999, 2000, 2001, 2006 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <assert.h>
28
29 #include "gpg.h"
30 #include "options.h"
31 #include "packet.h"
32 #include "errors.h"
33 #include "keydb.h"
34 #include "util.h"
35 #include "i18n.h"
36 #include "cipher.h"
37
38
39 /* There is currently no way to get the status of the quick random
40    generator flag from libgcrypt and it is not clear whether this
41    faked RNG is really a good idea.  Thus for now we use this stub
42    function but we should consider to entirely remove this fake RNG
43    stuff. */
44 static int
45 random_is_faked (void)
46 {
47   return 0;
48 }
49
50
51
52 void
53 release_sk_list( SK_LIST sk_list )
54 {
55     SK_LIST sk_rover;
56
57     for( ; sk_list; sk_list = sk_rover ) {
58         sk_rover = sk_list->next;
59         free_secret_key( sk_list->sk );
60         xfree( sk_list );
61     }
62 }
63
64
65 /* Check that we are only using keys which don't have
66  * the string "(insecure!)" or "not secure" or "do not use"
67  * in one of the user ids
68  */
69 static int
70 is_insecure( PKT_secret_key *sk )
71 {
72     u32 keyid[2];
73     KBNODE node = NULL, u;
74     int insecure = 0;
75
76     keyid_from_sk( sk, keyid );
77     node = get_pubkeyblock( keyid );
78     for ( u = node; u; u = u->next ) {
79         if ( u->pkt->pkttype == PKT_USER_ID ) {
80             PKT_user_id *id = u->pkt->pkt.user_id;
81             if ( id->attrib_data )
82                 continue; /* skip attribute packets */
83             if ( strstr( id->name, "(insecure!)" )
84                  || strstr( id->name, "not secure" )
85                  || strstr( id->name, "do not use" ) ) {
86                 insecure = 1;
87                 break;
88             }
89         }
90     }
91     release_kbnode( node );
92     
93     return insecure;
94 }
95
96 static int
97 key_present_in_sk_list(SK_LIST sk_list, PKT_secret_key *sk)
98 {
99     for (; sk_list; sk_list = sk_list->next) {
100         if ( !cmp_secret_keys(sk_list->sk, sk) )
101             return 0;
102     }
103     return -1;
104 }
105
106 static int
107 is_duplicated_entry (STRLIST list, STRLIST item)
108 {
109     for(; list && list != item; list = list->next) {
110         if ( !strcmp (list->d, item->d) )
111             return 1;
112     }
113     return 0;
114 }
115
116
117 int
118 build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list,
119                int unlock, unsigned int use )
120 {
121     SK_LIST sk_list = NULL;
122     int rc;
123
124     if( !locusr )
125       { /* use the default one */
126         PKT_secret_key *sk;
127
128         sk = xmalloc_clear( sizeof *sk );
129         sk->req_usage = use;
130         if( (rc = get_seckey_byname( sk, NULL, unlock )) ) {
131           free_secret_key( sk ); sk = NULL;
132           log_error("no default secret key: %s\n", g10_errstr(rc) );
133         }
134         else if( !(rc=openpgp_pk_test_algo2 (sk->pubkey_algo, use)) )
135           {
136             SK_LIST r;
137
138             if( random_is_faked() && !is_insecure( sk ) )
139               {
140                 log_info(_("key is not flagged as insecure - "
141                            "can't use it with the faked RNG!\n"));
142                 free_secret_key( sk ); sk = NULL;
143               }
144             else
145               {
146                 r = xmalloc( sizeof *r );
147                 r->sk = sk; sk = NULL;
148                 r->next = sk_list;
149                 r->mark = 0;
150                 sk_list = r;
151               }
152           }
153         else
154           {
155             free_secret_key( sk ); sk = NULL;
156             log_error("invalid default secret key: %s\n", g10_errstr(rc) );
157           }
158       }
159     else {
160         STRLIST locusr_orig = locusr;
161         for(; locusr; locusr = locusr->next ) {
162             PKT_secret_key *sk;
163             
164             rc = 0;
165             /* Do an early check agains duplicated entries.  However this
166              * won't catch all duplicates because the user IDs may be
167              * specified in different ways.
168              */
169             if ( is_duplicated_entry ( locusr_orig, locusr ) )
170               {
171                 log_error(_("skipped \"%s\": duplicated\n"), locusr->d );
172                 continue;
173               }
174             sk = xmalloc_clear( sizeof *sk );
175             sk->req_usage = use;
176             if( (rc = get_seckey_byname( sk, locusr->d, 0 )) )
177               {
178                 free_secret_key( sk ); sk = NULL;
179                 log_error(_("skipped \"%s\": %s\n"),
180                           locusr->d, g10_errstr(rc) );
181               }
182             else if ( key_present_in_sk_list(sk_list, sk) == 0) {
183                 free_secret_key(sk); sk = NULL;
184                 log_info(_("skipped: secret key already present\n"));
185             }
186             else if ( unlock && (rc = check_secret_key( sk, 0 )) )
187               {
188                 free_secret_key( sk ); sk = NULL;
189                 log_error(_("skipped \"%s\": %s\n"),
190                           locusr->d, g10_errstr(rc) );
191               }
192             else if( !(rc=openpgp_pk_test_algo2 (sk->pubkey_algo, use)) ) {
193                 SK_LIST r;
194
195                 if( sk->version == 4 && (use & PUBKEY_USAGE_SIG)
196                     && sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E )
197                   {
198                     log_info(_("skipped \"%s\": %s\n"),locusr->d,
199                              _("this is a PGP generated Elgamal key which"
200                                " is not secure for signatures!"));
201                     free_secret_key( sk ); sk = NULL;
202                   }
203                 else if( random_is_faked() && !is_insecure( sk ) ) {
204                     log_info(_("key is not flagged as insecure - "
205                                "can't use it with the faked RNG!\n"));
206                     free_secret_key( sk ); sk = NULL;
207                 }
208                 else {
209                     r = xmalloc( sizeof *r );
210                     r->sk = sk; sk = NULL;
211                     r->next = sk_list;
212                     r->mark = 0;
213                     sk_list = r;
214                 }
215             }
216             else {
217                 free_secret_key( sk ); sk = NULL;
218                 log_error("skipped \"%s\": %s\n", locusr->d, g10_errstr(rc) );
219             }
220         }
221     }
222
223
224     if( !rc && !sk_list ) {
225         log_error("no valid signators\n");
226         rc = G10ERR_NO_USER_ID;
227     }
228
229     if( rc )
230         release_sk_list( sk_list );
231     else
232         *ret_sk_list = sk_list;
233     return rc;
234 }
235