See ChangeLog: Thu Jul 1 12:47:31 CEST 1999 Werner Koch
[gnupg.git] / g10 / pkclist.c
1 /* pkclist.c
2  *      Copyright (C) 1998 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., 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 #include "status.h"
37 #include "i18n.h"
38
39
40 #define CONTROL_D ('D' - 'A' + 1)
41
42
43 static void
44 show_paths( ulong lid, int only_first )
45 {
46     void *context = NULL;
47     unsigned otrust, validity;
48     int last_level, level;
49
50     last_level = 0;
51     while( (level=enum_cert_paths( &context, &lid, &otrust, &validity)) != -1){
52         char *p;
53         int c, rc;
54         size_t n;
55         u32 keyid[2];
56         PKT_public_key *pk ;
57
58         if( level < last_level && only_first )
59             break;
60         last_level = level;
61
62         rc = keyid_from_lid( lid, keyid );
63         if( rc ) {
64             log_error("ooops: can't get keyid for lid %lu\n", lid);
65             return;
66         }
67
68         pk = m_alloc_clear( sizeof *pk );
69         rc = get_pubkey( pk, keyid );
70         if( rc ) {
71             log_error("key %08lX: public key not found: %s\n",
72                                     (ulong)keyid[1], g10_errstr(rc) );
73             return;
74         }
75
76         tty_printf("%*s%4u%c/%08lX.%lu %s \"",
77                   level*2, "",
78                   nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ),
79                   (ulong)keyid[1], lid, datestr_from_pk( pk ) );
80
81         c = trust_letter(otrust);
82         if( c )
83             putchar( c );
84         else
85             printf( "%02x", otrust );
86         putchar('/');
87         c = trust_letter(validity);
88         if( c )
89             putchar( c );
90         else
91             printf( "%02x", validity );
92         putchar(' ');
93
94         p = get_user_id( keyid, &n );
95         tty_print_string( p, n ),
96         m_free(p);
97         tty_printf("\"\n");
98         free_public_key( pk );
99     }
100     enum_cert_paths( &context, NULL, NULL, NULL ); /* release context */
101     tty_printf("\n");
102 }
103
104
105
106
107 /****************
108  * Returns true if an ownertrust has changed.
109  */
110 static int
111 do_edit_ownertrust( ulong lid, int mode, unsigned *new_trust )
112 {
113     char *p;
114     int rc;
115     size_t n;
116     u32 keyid[2];
117     PKT_public_key *pk ;
118     int changed=0;
119     int quit=0;
120     int show=0;
121
122     rc = keyid_from_lid( lid, keyid );
123     if( rc ) {
124         log_error("ooops: can't get keyid for lid %lu\n", lid);
125         return 0;
126     }
127
128     pk = m_alloc_clear( sizeof *pk );
129     rc = get_pubkey( pk, keyid );
130     if( rc ) {
131         log_error("key %08lX: public key not found: %s\n",
132                                 (ulong)keyid[1], g10_errstr(rc) );
133         return 0;
134     }
135
136     if( !mode ) {
137         tty_printf(_("No trust value assigned to %lu:\n"
138                    "%4u%c/%08lX %s \""), lid,
139                   nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ),
140                   (ulong)keyid[1], datestr_from_pk( pk ) );
141         p = get_user_id( keyid, &n );
142         tty_print_string( p, n ),
143         m_free(p);
144         tty_printf("\"\n\n");
145     }
146     tty_printf(_(
147 "Please decide how far you trust this user to correctly\n"
148 "verify other users' keys (by looking at passports,\n"
149 "checking fingerprints from different sources...)?\n\n"
150 " 1 = Don't know\n"
151 " 2 = I do NOT trust\n"
152 " 3 = I trust marginally\n"
153 " 4 = I trust fully\n"
154 " s = please show me more information\n") );
155     if( mode )
156         tty_printf(_(" m = back to the main menu\n"));
157     else
158         tty_printf(_(" q = quit\n"));
159     tty_printf("\n");
160
161     for(;;) {
162         /* a string with valid answers */
163         char *ans = _("sSmMqQ");
164
165         if( strlen(ans) != 6 )
166             BUG();
167         p = cpr_get("edit_ownertrust.value",_("Your decision? "));
168         trim_spaces(p);
169         cpr_kill_prompt();
170         if( *p && p[1] )
171             ;
172         else if( !p[1] && (*p >= '1' && *p <= '4') ) {
173             unsigned trust;
174             switch( *p ) {
175               case '1': trust = TRUST_UNDEFINED; break;
176               case '2': trust = TRUST_NEVER    ; break;
177               case '3': trust = TRUST_MARGINAL ; break;
178               case '4': trust = TRUST_FULLY    ; break;
179               default: BUG();
180             }
181             *new_trust = trust;
182             changed = 1;
183             break;
184         }
185         else if( *p == ans[0] || *p == ans[1] ) {
186             tty_printf(_(
187                 "Certificates leading to an ultimately trusted key:\n"));
188             show = 1;
189             break;
190         }
191         else if( mode && (*p == ans[2] || *p == ans[3] || *p == CONTROL_D ) ) {
192             break ; /* back to the menu */
193         }
194         else if( !mode && (*p == ans[4] || *p == ans[5] ) ) {
195             quit = 1;
196             break ; /* back to the menu */
197         }
198         m_free(p); p = NULL;
199     }
200     m_free(p);
201     m_free(pk);
202     return show? -2: quit? -1 : changed;
203 }
204
205
206 int
207 edit_ownertrust( ulong lid, int mode )
208 {
209     unsigned int trust;
210
211     for(;;) {
212         switch( do_edit_ownertrust( lid, mode, &trust ) ) {
213           case -1:
214             return 0;
215           case -2:
216             show_paths( lid, 1  );
217             break;
218           case 1:
219             trust &= ~TRUST_FLAG_DISABLED;
220             trust |= get_ownertrust( lid ) & TRUST_FLAG_DISABLED;
221             if( !update_ownertrust( lid, trust ) )
222                 return 1;
223             return 0;
224           default:
225             return 0;
226         }
227     }
228 }
229
230 static int
231 add_ownertrust_cb( ulong lid )
232 {
233     unsigned trust;
234     int rc = do_edit_ownertrust( lid, 0, &trust );
235
236     if( rc == 1 )
237         return trust & TRUST_MASK;
238     return rc > 0? 0 : rc;
239 }
240
241 /****************
242  * Try to add some more owner trusts (interactive)
243  * This function presents all the signator in a certificate
244  * chain who have no ownertrust value assigned.
245  * Returns: -1 if no ownertrust were added.
246  */
247 static int
248 add_ownertrust( PKT_public_key *pk, int *quit, unsigned *trustlevel )
249 {
250     int rc;
251     unsigned flags = 0;
252
253     *quit = 0;
254     *trustlevel = 0;
255     tty_printf(
256 _("Could not find a valid trust path to the key.  Let's see whether we\n"
257   "can assign some missing owner trust values.\n\n"));
258
259     rc = check_trust( pk, trustlevel, NULL, add_ownertrust_cb, &flags );
260
261     if( !(flags & 1) )
262         tty_printf(_("No path leading to one of our keys found.\n\n") );
263     else if( !(flags & 2) )
264         tty_printf(_("No certificates with undefined trust found.\n\n") );
265     else if( !(flags & 4) )
266         tty_printf(_("No trust values changed.\n\n") );
267
268     return (flags & 4)? 0:-1;
269 }
270
271 /****************
272  * Check whether we can trust this pk which has a trustlevel of TRUSTLEVEL
273  * Returns: true if we trust.
274  */
275 static int
276 do_we_trust( PKT_public_key *pk, int trustlevel )
277 {
278     int rc;
279     int did_add = 0;
280
281   retry:
282     if( (trustlevel & TRUST_FLAG_REVOKED) ) {
283         log_info(_("key %08lX: key has been revoked!\n"),
284                                         (ulong)keyid_from_pk( pk, NULL) );
285         if( opt.batch )
286             return 0;
287
288         if( !cpr_get_answer_is_yes("revoked_key.override",
289                                     _("Use this key anyway? ")) )
290             return 0;
291     }
292     else if( (trustlevel & TRUST_FLAG_SUB_REVOKED) ) {
293         log_info(_("key %08lX: subkey has been revoked!\n"),
294                                         (ulong)keyid_from_pk( pk, NULL) );
295         if( opt.batch )
296             return 0;
297
298         if( !cpr_get_answer_is_yes("revoked_key.override",
299                                     _("Use this key anyway? ")) )
300             return 0;
301     }
302
303
304     switch( (trustlevel & TRUST_MASK) ) {
305       case TRUST_UNKNOWN: /* No pubkey in trustDB: Insert and check again */
306         rc = insert_trust_record_by_pk( pk );
307         if( rc ) {
308             log_error("failed to insert it into the trustdb: %s\n",
309                                                       g10_errstr(rc) );
310             return 0; /* no */
311         }
312         rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
313         if( rc )
314             log_fatal("trust check after insert failed: %s\n",
315                                                       g10_errstr(rc) );
316         if( trustlevel == TRUST_UNKNOWN || trustlevel == TRUST_EXPIRED ) {
317             log_debug("do_we_trust: oops at %d\n", __LINE__ );
318             return 0;
319         }
320         return do_we_trust( pk, trustlevel );
321
322       case TRUST_EXPIRED:
323         log_info(_("%08lX: key has expired\n"),
324                                     (ulong)keyid_from_pk( pk, NULL) );
325         return 0; /* no */
326
327       case TRUST_UNDEFINED:
328         if( opt.batch || opt.answer_no )
329             log_info(_("%08lX: no info to calculate a trust probability\n"),
330                                         (ulong)keyid_from_pk( pk, NULL) );
331         else {
332             int quit;
333
334             rc = add_ownertrust( pk, &quit, &trustlevel );
335             if( !rc && !did_add && !quit ) {
336                 did_add = 1;
337                 goto retry;
338             }
339         }
340         return 0;
341
342       case TRUST_NEVER:
343         log_info(_("%08lX: We do NOT trust this key\n"),
344                                         (ulong)keyid_from_pk( pk, NULL) );
345         return 0; /* no */
346
347       case TRUST_MARGINAL:
348         log_info(
349        _("%08lX: It is not sure that this key really belongs to the owner\n"
350          "but it is accepted anyway\n"), (ulong)keyid_from_pk( pk, NULL) );
351         return 1; /* yes */
352
353       case TRUST_FULLY:
354         if( opt.verbose )
355             log_info(_("This key probably belongs to the owner\n"));
356         return 1; /* yes */
357
358       case TRUST_ULTIMATE:
359         if( opt.verbose )
360             log_info(_("This key belongs to us\n"));
361         return 1; /* yes */
362
363       default: BUG();
364     }
365
366     return 1; /* yes */
367 }
368
369
370 /****************
371  * wrapper around do_we_trust, so we can ask whether to use the
372  * key anyway.
373  */
374 static int
375 do_we_trust_pre( PKT_public_key *pk, int trustlevel )
376 {
377     int rc;
378
379     rc = do_we_trust( pk, trustlevel );
380
381     if( (trustlevel & TRUST_FLAG_REVOKED) && !rc )
382         return 0;
383     if( (trustlevel & TRUST_FLAG_SUB_REVOKED) && !rc )
384         return 0;
385     else if( !opt.batch && !rc ) {
386         char *p;
387         u32 keyid[2];
388         size_t n;
389
390         keyid_from_pk( pk, keyid);
391         tty_printf( "%4u%c/%08lX %s \"",
392                   nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ),
393                   (ulong)keyid[1], datestr_from_pk( pk ) );
394         p = get_user_id( keyid, &n );
395         tty_print_string( p, n ),
396         m_free(p);
397         tty_printf("\"\n\n");
398
399         tty_printf(_(
400 "It is NOT certain that the key belongs to its owner.\n"
401 "If you *really* know what you are doing, you may answer\n"
402 "the next question with yes\n\n") );
403
404         if( cpr_get_answer_is_yes("untrusted_key.override",
405                                   _("Use this key anyway? "))  )
406             rc = 1;
407
408         /* Hmmm: Should we set a flag to tell the user the user about
409          *       his decision the next time he encrypts for this recipient?
410          */
411     }
412     else if( opt.always_trust && !rc ) {
413         log_info(_("WARNING: Using untrusted key!\n"));
414         rc = 1;
415     }
416     return rc;
417 }
418
419
420
421 /****************
422  * Check whether we can trust this signature.
423  * Returns: Error if we shall not trust this signatures.
424  */
425 int
426 check_signatures_trust( PKT_signature *sig )
427 {
428     PKT_public_key *pk = m_alloc_clear( sizeof *pk );
429     int trustlevel;
430     int did_add = 0;
431     int rc=0;
432
433
434     if( opt.always_trust ) {
435         log_info(_("WARNING: Using untrusted key!\n"));
436         return 0;
437     }
438
439
440     rc = get_pubkey( pk, sig->keyid );
441     if( rc ) { /* this should not happen */
442         log_error("Ooops; the key vanished  - can't check the trust\n");
443         rc = G10ERR_NO_PUBKEY;
444         goto leave;
445     }
446
447     rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
448     if( rc ) {
449         log_error("check trust failed: %s\n", g10_errstr(rc));
450         goto leave;
451     }
452
453   retry:
454     if( (trustlevel & TRUST_FLAG_REVOKED) ) {
455         write_status( STATUS_KEYREVOKED );
456         log_info(_("WARNING: This key has been revoked by its owner!\n"));
457         log_info(_("         This could mean that the signature is forgery.\n"));
458     }
459     else if( (trustlevel & TRUST_FLAG_SUB_REVOKED) ) {
460         write_status( STATUS_KEYREVOKED );
461         log_info(_("WARNING: This subkey has been revoked by its owner!\n"));
462     }
463
464
465     switch( (trustlevel & TRUST_MASK) ) {
466       case TRUST_UNKNOWN: /* No pubkey in trustDB: Insert and check again */
467         rc = insert_trust_record_by_pk( pk );
468         if( rc ) {
469             log_error("failed to insert it into the trustdb: %s\n",
470                                                       g10_errstr(rc) );
471             goto leave;
472         }
473         rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
474         if( rc )
475             log_fatal("trust check after insert failed: %s\n",
476                                                       g10_errstr(rc) );
477         if( trustlevel == TRUST_UNKNOWN || trustlevel == TRUST_EXPIRED )
478             BUG();
479         goto retry;
480
481       case TRUST_EXPIRED:
482         log_info(_("Note: This key has expired!\n"));
483         break;
484
485       case TRUST_UNDEFINED:
486         if( did_add || opt.batch || opt.answer_no ) {
487             write_status( STATUS_TRUST_UNDEFINED );
488             log_info(_(
489             "WARNING: This key is not certified with a trusted signature!\n"));
490             log_info(_(
491             "         There is no indication that the "
492                                     "signature belongs to the owner.\n" ));
493         }
494         else {
495             int quit;
496             rc = add_ownertrust( pk, &quit, &trustlevel );
497             if( rc || quit ) {
498                 did_add = 1;
499                 rc = 0;
500             }
501             goto retry;
502         }
503         break;
504
505       case TRUST_NEVER:
506         write_status( STATUS_TRUST_NEVER );
507         log_info(_("WARNING: We do NOT trust this key!\n"));
508         log_info(_("         The signature is probably a FORGERY.\n"));
509         rc = G10ERR_BAD_SIGN;
510         break;
511
512       case TRUST_MARGINAL:
513         write_status( STATUS_TRUST_MARGINAL );
514         log_info(_(
515          "WARNING: This key is not certified with sufficiently trusted signatures!\n"
516                 ));
517         log_info(_(
518          "         It is not certain that the signature belongs to the owner.\n"
519                  ));
520         break;
521
522       case TRUST_FULLY:
523         write_status( STATUS_TRUST_FULLY );
524         break;
525
526       case TRUST_ULTIMATE:
527         write_status( STATUS_TRUST_ULTIMATE );
528         break;
529
530       default: BUG();
531     }
532
533
534   leave:
535     free_public_key( pk );
536     return rc;
537 }
538
539
540 void
541 release_pk_list( PK_LIST pk_list )
542 {
543     PK_LIST pk_rover;
544
545     for( ; pk_list; pk_list = pk_rover ) {
546         pk_rover = pk_list->next;
547         free_public_key( pk_list->pk );
548         m_free( pk_list );
549     }
550 }
551
552
553 static int
554 key_present_in_pk_list(PK_LIST pk_list, PKT_public_key *pk)
555 {
556     for( ; pk_list; pk_list = pk_list->next)
557         if (cmp_public_keys(pk_list->pk, pk) == 0)
558             return 0;
559
560     return -1;
561 }
562
563 int
564 build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
565 {
566     PK_LIST pk_list = NULL;
567     PKT_public_key *pk=NULL;
568     int rc=0;
569     int any_recipients=0;
570     STRLIST rov;
571
572     /* check whether there are any recipients in the list and build the
573      * list of the encrypt-to ones (we always trust them) */
574     for( rov = remusr; rov; rov = rov->next ) {
575         if( !(rov->flags & 1) )
576             any_recipients = 1;
577         else if( (use & PUBKEY_USAGE_ENC) && !opt.no_encrypt_to ) {
578             pk = m_alloc_clear( sizeof *pk );
579             pk->pubkey_usage = use;
580             if( (rc = get_pubkey_byname( NULL, pk, rov->d, NULL )) ) {
581                 free_public_key( pk ); pk = NULL;
582                 log_error(_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) );
583             }
584             else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) {
585
586                 /* Skip the actual key if the key is already present
587                  * in the list */
588                 if (key_present_in_pk_list(pk_list, pk) == 0) {
589                     free_public_key(pk); pk = NULL;
590                     log_info(_("%s: skipped: public key already present\n"),
591                                                             rov->d);
592                 }
593                 else {
594                     PK_LIST r;
595                     r = m_alloc( sizeof *r );
596                     r->pk = pk; pk = NULL;
597                     r->next = pk_list;
598                     r->mark = 0;
599                     pk_list = r;
600                 }
601             }
602             else {
603                 free_public_key( pk ); pk = NULL;
604                 log_error(_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) );
605             }
606         }
607     }
608
609     if( !any_recipients && !opt.batch ) { /* ask */
610         char *answer=NULL;
611
612         tty_printf(_(
613                 "You did not specify a user ID. (you may use \"-r\")\n\n"));
614         for(;;) {
615             rc = 0;
616             m_free(answer);
617             answer = cpr_get_utf8("pklist.user_id.enter",
618                                    _("Enter the user ID: "));
619             trim_spaces(answer);
620             cpr_kill_prompt();
621             if( !*answer )
622                 break;
623             if( pk )
624                 free_public_key( pk );
625             pk = m_alloc_clear( sizeof *pk );
626             pk->pubkey_usage = use;
627             rc = get_pubkey_byname( NULL, pk, answer, NULL );
628             if( rc )
629                 tty_printf(_("No such user ID.\n"));
630             else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) {
631                 int trustlevel;
632
633                 rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
634                 if( rc ) {
635                     log_error("error checking pk of `%s': %s\n",
636                                                       answer, g10_errstr(rc) );
637                 }
638                 else if( (trustlevel & TRUST_FLAG_DISABLED) ) {
639                     tty_printf(_("Public key is disabled.\n") );
640                 }
641                 else if( do_we_trust_pre( pk, trustlevel ) ) {
642                     PK_LIST r;
643
644                     r = m_alloc( sizeof *r );
645                     r->pk = pk; pk = NULL;
646                     r->next = pk_list;
647                     r->mark = 0;
648                     pk_list = r;
649                     any_recipients = 1;
650                     break;
651                 }
652             }
653         }
654         m_free(answer);
655         if( pk ) {
656             free_public_key( pk );
657             pk = NULL;
658         }
659     }
660     else {
661         any_recipients = 0;
662         for(; remusr; remusr = remusr->next ) {
663             if( (remusr->flags & 1) )
664                 continue; /* encrypt-to keys are already handled */
665
666             pk = m_alloc_clear( sizeof *pk );
667             pk->pubkey_usage = use;
668             if( (rc = get_pubkey_byname( NULL, pk, remusr->d, NULL )) ) {
669                 free_public_key( pk ); pk = NULL;
670                 log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) );
671             }
672             else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) {
673                 int trustlevel;
674
675                 rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
676                 if( rc ) {
677                     free_public_key( pk ); pk = NULL;
678                     log_error(_("%s: error checking key: %s\n"),
679                                                       remusr->d, g10_errstr(rc) );
680                 }
681                 else if( (trustlevel & TRUST_FLAG_DISABLED) ) {
682                     free_public_key(pk); pk = NULL;
683                     log_info(_("%s: skipped: public key is disabled\n"),
684                                                                     remusr->d);
685                 }
686                 else if( do_we_trust_pre( pk, trustlevel ) ) {
687                     /* note: do_we_trust may have changed the trustlevel */
688
689                     /* We have at least one valid recipient. It doesn't matters
690                      * if this recipient is already present. */
691                     any_recipients = 1;
692
693                     /* Skip the actual key if the key is already present
694                      * in the list */
695                     if (key_present_in_pk_list(pk_list, pk) == 0) {
696                         free_public_key(pk); pk = NULL;
697                         log_info(_("%s: skipped: public key already present\n"),
698                                                                     remusr->d);
699                     }
700                     else {
701                         PK_LIST r;
702                         r = m_alloc( sizeof *r );
703                         r->pk = pk; pk = NULL;
704                         r->next = pk_list;
705                         r->mark = 0;
706                         pk_list = r;
707                     }
708                 }
709                 else { /* we don't trust this pk */
710                     free_public_key( pk ); pk = NULL;
711                 }
712             }
713             else {
714                 free_public_key( pk ); pk = NULL;
715                 log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) );
716             }
717         }
718     }
719
720     if( !rc && !any_recipients ) {
721         log_error(_("no valid addressees\n"));
722         rc = G10ERR_NO_USER_ID;
723     }
724
725     if( rc )
726         release_pk_list( pk_list );
727     else
728         *ret_pk_list = pk_list;
729     return rc;
730 }
731
732
733
734 static int
735 algo_available( int preftype, int algo )
736 {
737     if( preftype == PREFTYPE_SYM ) {
738         if( algo == CIPHER_ALGO_TWOFISH )
739             return 0;  /* we don't want to generate Twofish messages for now*/
740         return algo && !check_cipher_algo( algo );
741     }
742     else if( preftype == PREFTYPE_HASH ) {
743         return algo && !check_digest_algo( algo );
744     }
745     else if( preftype == PREFTYPE_COMPR ) {
746         return !algo || algo == 1 || algo == 2;
747     }
748     else
749         return 0;
750 }
751
752 /****************
753  * Return -1 if we could not find an algorithm.
754  */
755 int
756 select_algo_from_prefs( PK_LIST pk_list, int preftype )
757 {
758     PK_LIST pkr;
759     u32 bits[8];
760     byte *pref = NULL;
761     size_t npref;
762     int i, j;
763     int compr_hack=0;
764     int any;
765
766     if( !pk_list )
767         return -1;
768
769     memset( bits, ~0, 8 * sizeof *bits );
770     for( pkr = pk_list; pkr; pkr = pkr->next ) {
771         u32 mask[8];
772
773         memset( mask, 0, 8 * sizeof *mask );
774         if( !pkr->pk->local_id ) { /* try to set the local id */
775             query_trust_info( pkr->pk, NULL );
776             if( !pkr->pk->local_id ) {
777                 log_debug("select_algo_from_prefs: can't get LID\n");
778                 continue;
779             }
780         }
781         if( preftype == PREFTYPE_SYM )
782             mask[0] |= (1<<2); /* 3DES is implicitly there */
783         m_free(pref);
784         pref = get_pref_data( pkr->pk->local_id, pkr->pk->namehash, &npref);
785         any = 0;
786         if( pref ) {
787            #if 0
788             log_hexdump("raw: ", pref, npref );
789            #endif
790             for(i=0; i+1 < npref; i+=2 ) {
791                 if( pref[i] == preftype ) {
792                     mask[pref[i+1]/32] |= 1 << (pref[i+1]%32);
793                     any = 1;
794                 }
795             }
796         }
797         if( (!pref || !any) && preftype == PREFTYPE_COMPR ) {
798             mask[0] |= 3; /* asume no_compression and old pgp */
799             compr_hack = 1;
800         }
801
802       #if 0
803         log_debug("mask=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n",
804                (ulong)mask[7], (ulong)mask[6], (ulong)mask[5], (ulong)mask[4],
805              (ulong)mask[3], (ulong)mask[2], (ulong)mask[1], (ulong)mask[0]);
806       #endif
807         for(i=0; i < 8; i++ )
808             bits[i] &= mask[i];
809       #if 0
810         log_debug("bits=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n",
811                (ulong)bits[7], (ulong)bits[6], (ulong)bits[5], (ulong)bits[4],
812              (ulong)bits[3], (ulong)bits[2], (ulong)bits[1], (ulong)bits[0]);
813       #endif
814     }
815     /* usable algorithms are now in bits
816      * We now use the last key from pk_list to select
817      * the algorithm we want to use. there are no
818      * preferences for the last key, we select the one
819      * corresponding to first set bit.
820      */
821     i = -1;
822     any = 0;
823     if( pref ) {
824         for(j=0; j+1 < npref; j+=2 ) {
825             if( pref[j] == preftype ) {
826                 if( (bits[pref[j+1]/32] & (1<<(pref[j+1]%32))) ) {
827                     if( algo_available( preftype, pref[j+1] ) ) {
828                         any = 1;
829                         i = pref[j+1];
830                         break;
831                     }
832                 }
833             }
834         }
835     }
836     if( !pref || !any ) {
837         for(j=0; j < 256; j++ )
838             if( (bits[j/32] & (1<<(j%32))) ) {
839                 if( algo_available( preftype, j ) ) {
840                     i = j;
841                     break;
842                 }
843             }
844     }
845   #if 0
846     log_debug("prefs of type %d: selected %d\n", preftype, i );
847   #endif
848     if( compr_hack && !i ) {
849         /* selected no compression, but we should check whether
850          * algorithm 1 is also available (the ordering is not relevant
851          * in this case). */
852         if( bits[0] & (1<<1) )
853             i = 1;  /* yep; we can use compression algo 1 */
854     }
855
856     m_free(pref);
857     return i;
858 }
859
860