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

Generated by: LCOV version 1.11