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

Generated by: LCOV version 1.11