LCOV - code coverage report
Current view: top level - g10 - skclist.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 50 114 43.9 %
Date: 2016-11-29 15:00:56 Functions: 5 6 83.3 %

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

Generated by: LCOV version 1.11