Trust stuff works partly.
[gnupg.git] / g10 / pkclist.c
1 /* pkclist.c
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This file is part of G10.
5  *
6  * G10 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  * G10 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
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 "options.h"
29 #include "packet.h"
30 #include "errors.h"
31 #include "keydb.h"
32 #include "memory.h"
33 #include "util.h"
34 #include "trustdb.h"
35 #include "ttyio.h"
36
37 /****************
38  * Returns true if a ownertrust has changed.
39  */
40 static int
41 query_ownertrust( ulong lid )
42 {
43     char *p;
44     int rc;
45     size_t n;
46     u32 keyid[2];
47     PKT_public_cert *pkc ;
48     int changed=0;
49
50     rc = keyid_from_trustdb( lid, keyid );
51     if( rc ) {
52         log_error("ooops: can't get keyid for lid %lu\n", lid);
53         return 0;
54     }
55
56     pkc = m_alloc_clear( sizeof *pkc );
57     rc = get_pubkey( pkc, keyid );
58     if( rc ) {
59         log_error("keyid %08lX: pubkey not found: %s\n",
60                                 (ulong)keyid[1], g10_errstr(rc) );
61         return 0;
62     }
63
64     tty_printf("No ownertrust defined for %lu:\n"
65                "%4u%c/%08lX %s \"", lid,
66               nbits_from_pkc( pkc ), pubkey_letter( pkc->pubkey_algo ),
67               (ulong)keyid[1], datestr_from_pkc( pkc ) );
68     p = get_user_id( keyid, &n );
69     tty_print_string( p, n ),
70     m_free(p);
71     tty_printf("\"\n\n"
72 "Please decide in how far do you trust this user to\n"
73 "correctly sign other users keys (looking at his passport,\n"
74 "checking the fingerprints from different sources ...)?\n\n"
75 " 1 = Don't know\n"
76 " 2 = I do NOT trust\n"
77 " 3 = I trust marginally\n"
78 " 4 = I trust fully\n"
79 " s = please show me more informations\n\n" );
80
81     for(;;) {
82         p = tty_get("Your decision? ");
83         trim_spaces(p);
84         tty_kill_prompt();
85         if( *p && p[1] )
86             ;
87         else if( *p == '?' ) {
88             tty_printf(
89 "It's up to you to assign a value here; this value will never be exported\n"
90 "to any 3rd party.  We need it to implement the web-of-trust; it has nothing\n"
91 "to do with the (implicitly created) web-of-certificates.\n");
92         }
93         else if( !p[1] && (*p >= '1' && *p <= '4') ) {
94             unsigned trust;
95             switch( *p ) {
96               case '1': trust = TRUST_UNDEFINED; break;
97               case '2': trust = TRUST_NEVER    ; break;
98               case '3': trust = TRUST_MARGINAL ; break;
99               case '4': trust = TRUST_FULLY    ; break;
100               default: BUG();
101             }
102             if( !update_ownertrust( lid, trust ) )
103                 changed++;
104             break;
105         }
106         else if( *p == 's' || *p == 'S' ) {
107             tty_printf("You will see a list of signators etc. here\n");
108         }
109         m_free(p); p = NULL;
110     }
111     m_free(p);
112     m_free(pkc);
113     return changed;
114 }
115
116
117 /****************
118  * Try to add some more owner trusts (interactive)
119  * Returns: -1 if no ownertrust were added.
120  */
121 static int
122 add_ownertrust( PKT_public_cert *pkc )
123 {
124     int rc;
125     void *context = NULL;
126     ulong lid;
127     unsigned trust;
128     int any=0;
129
130     tty_printf(
131 "Could not find a valid trust path to the key.  Lets see, wether we\n"
132 "can assign some missing owner trust values.\n\n");
133
134     rc = query_trust_record( pkc );
135     if( rc ) {
136         log_error("Ooops: not in trustdb\n");
137         return -1;
138     }
139
140     lid = pkc->local_id;
141     while( !(rc=enum_trust_web( &context, &lid )) ) {
142         rc = get_ownertrust( lid, &trust );
143         if( rc )
144             log_fatal("Ooops: couldn't get ownertrust for %lu\n", lid);
145         if( trust == TRUST_UNDEFINED || trust == TRUST_EXPIRED ||
146             trust == TRUST_UNKNOWN ) {
147             if( query_ownertrust( lid ) )
148                 any=1;
149         }
150     }
151     if( rc == -1 )
152         rc = 0;
153     enum_trust_web( &context, NULL ); /* close */
154
155
156     return rc? rc : any? 0:-1;
157 }
158
159
160 /****************
161  * Check wether we can trust this pkc which has a trustlevel of TRUSTLEVEL
162  * Returns: true if we trust.
163  */
164 static int
165 do_we_trust( PKT_public_cert *pkc, int trustlevel )
166 {
167     int rc;
168
169     switch( trustlevel ) {
170       case TRUST_UNKNOWN: /* No pubkey in trustDB: Insert and check again */
171         rc = insert_trust_record( pkc );
172         if( rc ) {
173             log_error("failed to insert it into the trustdb: %s\n",
174                                                       g10_errstr(rc) );
175             return 0; /* no */
176         }
177         rc = check_trust( pkc, &trustlevel );
178         if( rc )
179             log_fatal("trust check after insert failed: %s\n",
180                                                       g10_errstr(rc) );
181         if( trustlevel == TRUST_UNKNOWN || trustlevel == TRUST_EXPIRED )
182             BUG();
183         return do_we_trust( pkc, trustlevel );
184
185       case TRUST_EXPIRED:
186         log_error("trust has expired: NOT yet implemented\n");
187         return 0; /* no */
188
189       case TRUST_UNDEFINED:
190         if( opt.batch || opt.answer_no )
191             log_info("no info to calculate a trust probability\n");
192         else {
193             rc = add_ownertrust( pkc );
194             if( !rc ) {
195                 rc = check_trust( pkc, &trustlevel );
196                 if( rc )
197                     log_fatal("trust check after add_ownertrust failed: %s\n",
198                                                               g10_errstr(rc) );
199                 /* FIXME: this is recursive; we better should unroll it */
200                 return do_we_trust( pkc, trustlevel );
201             }
202         }
203         return 0; /* no */
204
205       case TRUST_NEVER:
206         log_info("We do NOT trust this key\n");
207         return 0; /* no */
208
209       case TRUST_MARGINAL:
210         log_info("I'm not sure wether this keys really belongs to the owner\n"
211                  "but I proceed anyway\n");
212         return 1; /* yes */
213
214       case TRUST_FULLY:
215         log_info("This key probably belongs to the owner\n");
216         return 1; /* yes */
217
218       case TRUST_ULTIMATE:
219         log_info("Our own keys is always good.\n");
220         return 1; /* yes */
221
222       default: BUG();
223     }
224
225
226     /* Eventuell fragen falls der trustlevel nicht ausreichend ist */
227
228
229     return 1; /* yes */
230 }
231
232
233
234 void
235 release_pkc_list( PKC_LIST pkc_list )
236 {
237     PKC_LIST pkc_rover;
238
239     for( ; pkc_list; pkc_list = pkc_rover ) {
240         pkc_rover = pkc_list->next;
241         free_public_cert( pkc_list->pkc );
242         m_free( pkc_list );
243     }
244 }
245
246 int
247 build_pkc_list( STRLIST remusr, PKC_LIST *ret_pkc_list )
248 {
249     PKC_LIST pkc_list = NULL;
250     int rc;
251
252     if( !remusr ) { /* ask!!! */
253         log_bug("ask for public key nyi\n");
254     }
255     else {
256         for(; remusr; remusr = remusr->next ) {
257             PKT_public_cert *pkc;
258
259             pkc = m_alloc_clear( sizeof *pkc );
260             if( (rc = get_pubkey_byname( pkc, remusr->d )) ) {
261                 free_public_cert( pkc ); pkc = NULL;
262                 log_error("skipped '%s': %s\n", remusr->d, g10_errstr(rc) );
263             }
264             else if( !(rc=check_pubkey_algo(pkc->pubkey_algo)) ) {
265                 int trustlevel;
266
267                 rc = check_trust( pkc, &trustlevel );
268                 if( rc ) {
269                     free_public_cert( pkc ); pkc = NULL;
270                     log_error("error checking pkc of '%s': %s\n",
271                                                       remusr->d, g10_errstr(rc) );
272                 }
273                 else if( do_we_trust( pkc, trustlevel ) ) {
274                     /* note: do_we_trust may have changed the trustlevel */
275                     PKC_LIST r;
276
277                     r = m_alloc( sizeof *r );
278                     r->pkc = pkc; pkc = NULL;
279                     r->next = pkc_list;
280                     r->mark = 0;
281                     pkc_list = r;
282                 }
283                 else { /* we don't trust this pkc */
284                     free_public_cert( pkc ); pkc = NULL;
285                 }
286             }
287             else {
288                 free_public_cert( pkc ); pkc = NULL;
289                 log_error("skipped '%s': %s\n", remusr->d, g10_errstr(rc) );
290             }
291         }
292     }
293
294
295     if( !rc && !pkc_list ) {
296         log_error("no valid addressees\n");
297         rc = G10ERR_NO_USER_ID;
298     }
299
300     if( rc )
301         release_pkc_list( pkc_list );
302     else
303         *ret_pkc_list = pkc_list;
304     return rc;
305 }
306
307