LCOV - code coverage report
Current view: top level - g10 - kbnode.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 108 196 55.1 %
Date: 2016-11-29 15:00:56 Functions: 15 18 83.3 %

          Line data    Source code
       1             : /* kbnode.c -  keyblock node utility functions
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2002,
       3             :  *               2005, 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             : 
      26             : #include "gpg.h"
      27             : #include "util.h"
      28             : #include "../common/init.h"
      29             : #include "packet.h"
      30             : #include "keydb.h"
      31             : 
      32             : #define USE_UNUSED_NODES 1
      33             : 
      34             : static int cleanup_registered;
      35             : static KBNODE unused_nodes;
      36             : 
      37             : static void
      38        1063 : release_unused_nodes (void)
      39             : {
      40             : #if USE_UNUSED_NODES
      41       10429 :   while (unused_nodes)
      42             :     {
      43        8303 :       kbnode_t next = unused_nodes->next;
      44        8303 :       xfree (unused_nodes);
      45        8303 :       unused_nodes = next;
      46             :     }
      47             : #endif /*USE_UNUSED_NODES*/
      48        1063 : }
      49             : 
      50             : 
      51             : static kbnode_t
      52       21484 : alloc_node (void)
      53             : {
      54             :   kbnode_t n;
      55             : 
      56       21484 :   n = unused_nodes;
      57       21484 :   if (n)
      58       12832 :     unused_nodes = n->next;
      59             :   else
      60             :     {
      61        8652 :       if (!cleanup_registered)
      62             :         {
      63        1065 :           cleanup_registered = 1;
      64        1065 :           register_mem_cleanup_func (release_unused_nodes);
      65             :         }
      66        8652 :       n = xmalloc (sizeof *n);
      67             :     }
      68       21484 :   n->next = NULL;
      69       21484 :   n->pkt = NULL;
      70       21484 :   n->flag = 0;
      71       21484 :   n->private_flag=0;
      72       21484 :   n->recno = 0;
      73       21484 :   return n;
      74             : }
      75             : 
      76             : static void
      77       21155 : free_node( KBNODE n )
      78             : {
      79       21155 :   if (n)
      80             :     {
      81             : #if USE_UNUSED_NODES
      82       21155 :       n->next = unused_nodes;
      83       21155 :       unused_nodes = n;
      84             : #else
      85             :       xfree (n);
      86             : #endif
      87             :     }
      88       21155 : }
      89             : 
      90             : 
      91             : 
      92             : KBNODE
      93       21422 : new_kbnode( PACKET *pkt )
      94             : {
      95       21422 :     KBNODE n = alloc_node();
      96       21422 :     n->pkt = pkt;
      97       21422 :     return n;
      98             : }
      99             : 
     100             : 
     101             : KBNODE
     102          62 : clone_kbnode( KBNODE node )
     103             : {
     104          62 :     KBNODE n = alloc_node();
     105             : 
     106          62 :     n->pkt = node->pkt;
     107          62 :     n->private_flag = node->private_flag | 2; /* mark cloned */
     108          62 :     return n;
     109             : }
     110             : 
     111             : 
     112             : void
     113        8004 : release_kbnode( KBNODE n )
     114             : {
     115             :     KBNODE n2;
     116             : 
     117       37096 :     while( n ) {
     118       21088 :         n2 = n->next;
     119       21088 :         if( !is_cloned_kbnode(n) ) {
     120       21026 :             free_packet( n->pkt );
     121       21026 :             xfree( n->pkt );
     122             :         }
     123       21088 :         free_node( n );
     124       21088 :         n = n2;
     125             :     }
     126        8004 : }
     127             : 
     128             : 
     129             : /****************
     130             :  * Delete NODE.
     131             :  * Note: This only works with walk_kbnode!!
     132             :  */
     133             : void
     134          67 : delete_kbnode( KBNODE node )
     135             : {
     136          67 :     node->private_flag |= 1;
     137          67 : }
     138             : 
     139             : /****************
     140             :  * Append NODE to ROOT.  ROOT must exist!
     141             :  */
     142             : void
     143        1976 : add_kbnode( KBNODE root, KBNODE node )
     144             : {
     145             :     KBNODE n1;
     146             : 
     147        1976 :     for(n1=root; n1->next; n1 = n1->next)
     148             :         ;
     149        1976 :     n1->next = node;
     150        1976 : }
     151             : 
     152             : /****************
     153             :  * Insert NODE into the list after root but before a packet which is not of
     154             :  * type PKTTYPE
     155             :  * (only if PKTTYPE != 0)
     156             :  */
     157             : void
     158          15 : insert_kbnode( KBNODE root, KBNODE node, int pkttype )
     159             : {
     160          15 :     if( !pkttype ) {
     161           8 :         node->next = root->next;
     162           8 :         root->next = node;
     163             :     }
     164             :     else {
     165             :         KBNODE n1;
     166             : 
     167          14 :         for(n1=root; n1->next;       n1 = n1->next)
     168          14 :             if( pkttype != n1->next->pkt->pkttype ) {
     169           7 :                 node->next = n1->next;
     170           7 :                 n1->next = node;
     171          22 :                 return;
     172             :             }
     173             :         /* no such packet, append */
     174           0 :         node->next = NULL;
     175           0 :         n1->next = node;
     176             :     }
     177             : }
     178             : 
     179             : 
     180             : /****************
     181             :  * Find the previous node (if PKTTYPE = 0) or the previous node
     182             :  * with pkttype PKTTYPE in the list starting with ROOT of NODE.
     183             :  */
     184             : KBNODE
     185        1108 : find_prev_kbnode( KBNODE root, KBNODE node, int pkttype )
     186             : {
     187             :     KBNODE n1;
     188             : 
     189        6013 :     for (n1=NULL; root && root != node; root = root->next ) {
     190        4905 :         if (!pkttype ||root->pkt->pkttype == pkttype)
     191        1573 :             n1 = root;
     192             :     }
     193        1108 :     return n1;
     194             : }
     195             : 
     196             : /****************
     197             :  * Ditto, but find the next packet.  The behaviour is trivial if
     198             :  * PKTTYPE is 0 but if it is specified, the next node with a packet
     199             :  * of this type is returned.  The function has some knowledge about
     200             :  * the valid ordering of packets: e.g. if the next signature packet
     201             :  * is requested, the function will not return one if it encounters
     202             :  * a user-id.
     203             :  */
     204             : KBNODE
     205        2352 : find_next_kbnode( KBNODE node, int pkttype )
     206             : {
     207        3324 :     for( node=node->next ; node; node = node->next ) {
     208        2677 :         if( !pkttype )
     209         992 :             return node;
     210        1685 :         else if( pkttype == PKT_USER_ID
     211        1101 :                  && (   node->pkt->pkttype == PKT_PUBLIC_KEY
     212        1101 :                      || node->pkt->pkttype == PKT_SECRET_KEY ) )
     213           0 :             return NULL;
     214        1685 :         else if( pkttype == PKT_SIGNATURE
     215         358 :                  && (   node->pkt->pkttype == PKT_USER_ID
     216         358 :                      || node->pkt->pkttype == PKT_PUBLIC_KEY
     217         358 :                      || node->pkt->pkttype == PKT_SECRET_KEY ) )
     218           0 :             return NULL;
     219        1685 :         else if( node->pkt->pkttype == pkttype )
     220         713 :             return node;
     221             :     }
     222         647 :     return NULL;
     223             : }
     224             : 
     225             : 
     226             : KBNODE
     227         449 : find_kbnode( KBNODE node, int pkttype )
     228             : {
     229         463 :     for( ; node; node = node->next ) {
     230         463 :         if( node->pkt->pkttype == pkttype )
     231         449 :             return node;
     232             :     }
     233           0 :     return NULL;
     234             : }
     235             : 
     236             : 
     237             : 
     238             : /****************
     239             :  * Walk through a list of kbnodes. This function returns
     240             :  * the next kbnode for each call; before using the function the first
     241             :  * time, the caller must set CONTEXT to NULL (This has simply the effect
     242             :  * to start with ROOT).
     243             :  */
     244             : KBNODE
     245        6344 : walk_kbnode( KBNODE root, KBNODE *context, int all )
     246             : {
     247             :     KBNODE n;
     248             : 
     249             :     do {
     250        6344 :         if( !*context ) {
     251         919 :             *context = root;
     252         919 :             n = root;
     253             :         }
     254             :         else {
     255        5425 :             n = (*context)->next;
     256        5425 :             *context = n;
     257             :         }
     258        6344 :     } while( !all && n && is_deleted_kbnode(n) );
     259             : 
     260        6338 :     return n;
     261             : }
     262             : 
     263             : void
     264         316 : clear_kbnode_flags( KBNODE n )
     265             : {
     266        2116 :     for( ; n; n = n->next ) {
     267        1800 :         n->flag = 0;
     268             :     }
     269         316 : }
     270             : 
     271             : 
     272             : /****************
     273             :  * Commit changes made to the kblist at ROOT. Note that ROOT my change,
     274             :  * and it is therefore passed by reference.
     275             :  * The function has the effect of removing all nodes marked as deleted.
     276             :  * returns true if any node has been changed
     277             :  */
     278             : int
     279         605 : commit_kbnode( KBNODE *root )
     280             : {
     281             :     KBNODE n, nl;
     282         605 :     int changed = 0;
     283             : 
     284        4234 :     for( n = *root, nl=NULL; n; n = nl->next ) {
     285        3629 :         if( is_deleted_kbnode(n) ) {
     286          67 :             if( n == *root )
     287           3 :                 *root = nl = n->next;
     288             :             else
     289          64 :                 nl->next = n->next;
     290          67 :             if( !is_cloned_kbnode(n) ) {
     291          67 :                 free_packet( n->pkt );
     292          67 :                 xfree( n->pkt );
     293             :             }
     294          67 :             free_node( n );
     295          67 :             changed = 1;
     296             :         }
     297             :         else
     298        3562 :             nl = n;
     299             :     }
     300         605 :     return changed;
     301             : }
     302             : 
     303             : void
     304           0 : remove_kbnode( KBNODE *root, KBNODE node )
     305             : {
     306             :     KBNODE n, nl;
     307             : 
     308           0 :     for( n = *root, nl=NULL; n; n = nl->next ) {
     309           0 :         if( n == node ) {
     310           0 :             if( n == *root )
     311           0 :                 *root = nl = n->next;
     312             :             else
     313           0 :                 nl->next = n->next;
     314           0 :             if( !is_cloned_kbnode(n) ) {
     315           0 :                 free_packet( n->pkt );
     316           0 :                 xfree( n->pkt );
     317             :             }
     318           0 :             free_node( n );
     319             :         }
     320             :         else
     321           0 :             nl = n;
     322             :     }
     323           0 : }
     324             : 
     325             : 
     326             : /****************
     327             :  * Move NODE behind right after WHERE or to the beginning if WHERE is NULL.
     328             :  */
     329             : void
     330           0 : move_kbnode( KBNODE *root, KBNODE node, KBNODE where )
     331             : {
     332             :     KBNODE tmp, prev;
     333             : 
     334           0 :     if( !root || !*root || !node )
     335           0 :         return;  /* sanity check */
     336           0 :     for( prev = *root; prev && prev->next != node; prev = prev->next )
     337             :         ;
     338           0 :     if( !prev )
     339           0 :         return; /* node is not in the list */
     340             : 
     341           0 :     if( !where ) {  /* move node before root */
     342           0 :         if( node == *root ) /* move to itself */
     343           0 :             return;
     344           0 :         prev->next = node->next;
     345           0 :         node->next = *root;
     346           0 :         *root = node;
     347           0 :         return;
     348             :     }
     349             :     /* move it after where */
     350           0 :     if( node == where )
     351           0 :         return;
     352           0 :     tmp = node->next;
     353           0 :     node->next = where->next;
     354           0 :     where->next = node;
     355           0 :     prev->next = tmp;
     356             : }
     357             : 
     358             : 
     359             : 
     360             : 
     361             : void
     362           0 : dump_kbnode (KBNODE node)
     363             : {
     364           0 :   for (; node; node = node->next )
     365             :     {
     366             :       const char *s;
     367           0 :       switch (node->pkt->pkttype)
     368             :         {
     369           0 :         case 0:         s="empty"; break;
     370           0 :         case PKT_PUBLIC_KEY:    s="public-key"; break;
     371           0 :         case PKT_SECRET_KEY:    s="secret-key"; break;
     372           0 :         case PKT_SECRET_SUBKEY: s= "secret-subkey"; break;
     373           0 :         case PKT_PUBKEY_ENC:    s="public-enc"; break;
     374           0 :         case PKT_SIGNATURE:     s="signature"; break;
     375           0 :         case PKT_ONEPASS_SIG: s="onepass-sig"; break;
     376           0 :         case PKT_USER_ID:       s="user-id"; break;
     377           0 :         case PKT_PUBLIC_SUBKEY: s="public-subkey"; break;
     378           0 :         case PKT_COMMENT:       s="comment"; break;
     379           0 :         case PKT_RING_TRUST:    s="trust"; break;
     380           0 :         case PKT_PLAINTEXT:     s="plaintext"; break;
     381           0 :         case PKT_COMPRESSED:    s="compressed"; break;
     382           0 :         case PKT_ENCRYPTED:     s="encrypted"; break;
     383           0 :         case PKT_GPG_CONTROL: s="gpg-control"; break;
     384           0 :         default:                s="unknown"; break;
     385             :         }
     386           0 :       log_debug ("node %p %02x/%02x type=%s",
     387             :                  node, node->flag, node->private_flag, s);
     388           0 :       if (node->pkt->pkttype == PKT_USER_ID)
     389             :         {
     390           0 :           PKT_user_id *uid = node->pkt->pkt.user_id;
     391           0 :           log_printf ("  \"");
     392           0 :           es_write_sanitized (log_get_stream (), uid->name, uid->len,
     393             :                               NULL, NULL);
     394           0 :           log_printf ("\" %c%c%c%c\n",
     395           0 :                       uid->is_expired? 'e':'.',
     396           0 :                       uid->is_revoked? 'r':'.',
     397           0 :                       uid->created?    'v':'.',
     398           0 :                       uid->is_primary? 'p':'.' );
     399             :         }
     400           0 :       else if (node->pkt->pkttype == PKT_SIGNATURE)
     401             :         {
     402           0 :           log_printf ("  class=%02x keyid=%08lX ts=%lu\n",
     403           0 :                       node->pkt->pkt.signature->sig_class,
     404           0 :                       (ulong)node->pkt->pkt.signature->keyid[1],
     405           0 :                       (ulong)node->pkt->pkt.signature->timestamp);
     406             :         }
     407           0 :       else if (node->pkt->pkttype == PKT_GPG_CONTROL)
     408             :         {
     409           0 :           log_printf (" ctrl=%d len=%u\n",
     410           0 :                       node->pkt->pkt.gpg_control->control,
     411           0 :                       (unsigned int)node->pkt->pkt.gpg_control->datalen);
     412             :         }
     413           0 :       else if (node->pkt->pkttype == PKT_PUBLIC_KEY
     414           0 :                || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
     415           0 :         {
     416           0 :           PKT_public_key *pk = node->pkt->pkt.public_key;
     417             : 
     418           0 :           log_printf ("  keyid=%08lX a=%d u=%d %c%c%c%c\n",
     419           0 :                       (ulong)keyid_from_pk( pk, NULL ),
     420           0 :                       pk->pubkey_algo, pk->pubkey_usage,
     421           0 :                       pk->has_expired? 'e':'.',
     422           0 :                       pk->flags.revoked? 'r':'.',
     423           0 :                       pk->flags.valid?    'v':'.',
     424           0 :                       pk->flags.mdc?   'm':'.');
     425             :         }
     426             :       else
     427           0 :         log_printf ("\n");
     428             : 
     429           0 :       log_flush ();
     430             :     }
     431           0 : }

Generated by: LCOV version 1.11