LCOV - code coverage report
Current view: top level - agent - trustlist.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 6 358 1.7 %
Date: 2016-11-29 15:00:56 Functions: 1 13 7.7 %

          Line data    Source code
       1             : /* trustlist.c - Maintain the list of trusted keys
       2             :  * Copyright (C) 2002, 2004, 2006, 2007, 2009,
       3             :  *               2012 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 <errno.h>
      23             : #include <stdio.h>
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : #include <ctype.h>
      27             : #include <assert.h>
      28             : #include <unistd.h>
      29             : #include <sys/stat.h>
      30             : #include <npth.h>
      31             : 
      32             : #include "agent.h"
      33             : #include <assuan.h> /* fixme: need a way to avoid assuan calls here */
      34             : #include "i18n.h"
      35             : 
      36             : 
      37             : /* A structure to store the information from the trust file. */
      38             : struct trustitem_s
      39             : {
      40             :   struct
      41             :   {
      42             :     int disabled:1;       /* This entry is disabled.  */
      43             :     int for_pgp:1;        /* Set by '*' or 'P' as first flag. */
      44             :     int for_smime:1;      /* Set by '*' or 'S' as first flag. */
      45             :     int relax:1;          /* Relax checking of root certificate
      46             :                              constraints. */
      47             :     int cm:1;             /* Use chain model for validation. */
      48             :   } flags;
      49             :   unsigned char fpr[20];  /* The binary fingerprint. */
      50             : };
      51             : typedef struct trustitem_s trustitem_t;
      52             : 
      53             : /* Malloced table and its allocated size with all trust items. */
      54             : static trustitem_t *trusttable;
      55             : static size_t trusttablesize;
      56             : /* A mutex used to protect the table. */
      57             : static npth_mutex_t trusttable_lock;
      58             : 
      59             : 
      60             : static const char headerblurb[] =
      61             : "# This is the list of trusted keys.  Comment lines, like this one, as\n"
      62             : "# well as empty lines are ignored.  Lines have a length limit but this\n"
      63             : "# is not a serious limitation as the format of the entries is fixed and\n"
      64             : "# checked by gpg-agent.  A non-comment line starts with optional white\n"
      65             : "# space, followed by the SHA-1 fingerpint in hex, followed by a flag\n"
      66             : "# which may be one of 'P', 'S' or '*' and optionally followed by a list of\n"
      67             : "# other flags.  The fingerprint may be prefixed with a '!' to mark the\n"
      68             : "# key as not trusted.  You should give the gpg-agent a HUP or run the\n"
      69             : "# command \"gpgconf --reload gpg-agent\" after changing this file.\n"
      70             : "\n\n"
      71             : "# Include the default trust list\n"
      72             : "include-default\n"
      73             : "\n";
      74             : 
      75             : 
      76             : /* This function must be called once to initialize this module.  This
      77             :    has to be done before a second thread is spawned.  We can't do the
      78             :    static initialization because Pth emulation code might not be able
      79             :    to do a static init; in particular, it is not possible for W32. */
      80             : void
      81          50 : initialize_module_trustlist (void)
      82             : {
      83             :   static int initialized;
      84             :   int err;
      85             : 
      86          50 :   if (!initialized)
      87             :     {
      88          50 :       err = npth_mutex_init (&trusttable_lock, NULL);
      89          50 :       if (err)
      90           0 :         log_fatal ("failed to init mutex in %s: %s\n", __FILE__,strerror (err));
      91          50 :       initialized = 1;
      92             :     }
      93          50 : }
      94             : 
      95             : 
      96             : 
      97             : 
      98             : static void
      99           0 : lock_trusttable (void)
     100             : {
     101             :   int err;
     102             : 
     103           0 :   err = npth_mutex_lock (&trusttable_lock);
     104           0 :   if (err)
     105           0 :     log_fatal ("failed to acquire mutex in %s: %s\n", __FILE__, strerror (err));
     106           0 : }
     107             : 
     108             : 
     109             : static void
     110           0 : unlock_trusttable (void)
     111             : {
     112             :   int err;
     113             : 
     114           0 :   err = npth_mutex_unlock (&trusttable_lock);
     115           0 :   if (err)
     116           0 :     log_fatal ("failed to release mutex in %s: %s\n", __FILE__, strerror (err));
     117           0 : }
     118             : 
     119             : 
     120             : /* Clear the trusttable.  The caller needs to make sure that the
     121             :    trusttable is locked.  */
     122             : static inline void
     123           0 : clear_trusttable (void)
     124             : {
     125           0 :   xfree (trusttable);
     126           0 :   trusttable = NULL;
     127           0 :   trusttablesize = 0;
     128           0 : }
     129             : 
     130             : 
     131             : static gpg_error_t
     132           0 : read_one_trustfile (const char *fname, int allow_include,
     133             :                     trustitem_t **addr_of_table,
     134             :                     size_t *addr_of_tablesize,
     135             :                     int *addr_of_tableidx)
     136             : {
     137           0 :   gpg_error_t err = 0;
     138             :   estream_t fp;
     139             :   int n, c;
     140             :   char *p, line[256];
     141             :   trustitem_t *table, *ti;
     142             :   int tableidx;
     143             :   size_t tablesize;
     144           0 :   int lnr = 0;
     145             : 
     146           0 :   table = *addr_of_table;
     147           0 :   tablesize = *addr_of_tablesize;
     148           0 :   tableidx = *addr_of_tableidx;
     149             : 
     150           0 :   fp = es_fopen (fname, "r");
     151           0 :   if (!fp)
     152             :     {
     153           0 :       err = gpg_error_from_syserror ();
     154           0 :       log_error (_("error opening '%s': %s\n"), fname, gpg_strerror (err));
     155           0 :       goto leave;
     156             :     }
     157             : 
     158           0 :   while (es_fgets (line, DIM(line)-1, fp))
     159             :     {
     160           0 :       lnr++;
     161             : 
     162           0 :       n = strlen (line);
     163           0 :       if (!n || line[n-1] != '\n')
     164             :         {
     165             :           /* Eat until end of line. */
     166           0 :           while ( (c=es_getc (fp)) != EOF && c != '\n')
     167             :             ;
     168           0 :           err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
     169             :                            : GPG_ERR_INCOMPLETE_LINE);
     170           0 :           log_error (_("file '%s', line %d: %s\n"),
     171             :                      fname, lnr, gpg_strerror (err));
     172           0 :           continue;
     173             :         }
     174           0 :       line[--n] = 0; /* Chop the LF. */
     175           0 :       if (n && line[n-1] == '\r')
     176           0 :         line[--n] = 0; /* Chop an optional CR. */
     177             : 
     178             :       /* Allow for empty lines and spaces */
     179           0 :       for (p=line; spacep (p); p++)
     180             :         ;
     181           0 :       if (!*p || *p == '#')
     182           0 :         continue;
     183             : 
     184           0 :       if (!strncmp (p, "include-default", 15)
     185           0 :           && (!p[15] || spacep (p+15)))
     186             :         {
     187             :           char *etcname;
     188             :           gpg_error_t err2;
     189             : 
     190           0 :           if (!allow_include)
     191             :             {
     192           0 :               log_error (_("statement \"%s\" ignored in '%s', line %d\n"),
     193             :                          "include-default", fname, lnr);
     194           0 :               continue;
     195             :             }
     196             :           /* fixme: Should check for trailing garbage.  */
     197             : 
     198           0 :           etcname = make_filename (gnupg_sysconfdir (), "trustlist.txt", NULL);
     199           0 :           if ( !strcmp (etcname, fname) ) /* Same file. */
     200           0 :             log_info (_("statement \"%s\" ignored in '%s', line %d\n"),
     201             :                       "include-default", fname, lnr);
     202           0 :           else if ( access (etcname, F_OK) && errno == ENOENT )
     203             :             {
     204             :               /* A non existent system trustlist is not an error.
     205             :                  Just print a note. */
     206           0 :               log_info (_("system trustlist '%s' not available\n"), etcname);
     207             :             }
     208             :           else
     209             :             {
     210           0 :               err2 = read_one_trustfile (etcname, 0,
     211             :                                          &table, &tablesize, &tableidx);
     212           0 :               if (err2)
     213           0 :                 err = err2;
     214             :             }
     215           0 :           xfree (etcname);
     216             : 
     217           0 :           continue;
     218             :         }
     219             : 
     220           0 :       if (tableidx == tablesize)  /* Need more space. */
     221             :         {
     222             :           trustitem_t *tmp;
     223             :           size_t tmplen;
     224             : 
     225           0 :           tmplen = tablesize + 20;
     226           0 :           tmp = xtryrealloc (table, tmplen * sizeof *table);
     227           0 :           if (!tmp)
     228             :             {
     229           0 :               err = gpg_error_from_syserror ();
     230           0 :               goto leave;
     231             :             }
     232           0 :           table = tmp;
     233           0 :           tablesize = tmplen;
     234             :         }
     235             : 
     236           0 :       ti = table + tableidx;
     237             : 
     238           0 :       memset (&ti->flags, 0, sizeof ti->flags);
     239           0 :       if (*p == '!')
     240             :         {
     241           0 :           ti->flags.disabled = 1;
     242           0 :           p++;
     243           0 :           while (spacep (p))
     244           0 :             p++;
     245             :         }
     246             : 
     247           0 :       n = hexcolon2bin (p, ti->fpr, 20);
     248           0 :       if (n < 0)
     249             :         {
     250           0 :           log_error (_("bad fingerprint in '%s', line %d\n"), fname, lnr);
     251           0 :           err = gpg_error (GPG_ERR_BAD_DATA);
     252           0 :           continue;
     253             :         }
     254           0 :       p += n;
     255           0 :       for (; spacep (p); p++)
     256             :         ;
     257             : 
     258             :       /* Process the first flag which needs to be the first for
     259             :          backward compatibility. */
     260           0 :       if (!*p || *p == '*' )
     261             :         {
     262           0 :           ti->flags.for_smime = 1;
     263           0 :           ti->flags.for_pgp = 1;
     264             :         }
     265           0 :       else if ( *p == 'P' || *p == 'p')
     266             :         {
     267           0 :           ti->flags.for_pgp = 1;
     268             :         }
     269           0 :       else if ( *p == 'S' || *p == 's')
     270             :         {
     271           0 :           ti->flags.for_smime = 1;
     272             :         }
     273             :       else
     274             :         {
     275           0 :           log_error (_("invalid keyflag in '%s', line %d\n"), fname, lnr);
     276           0 :           err = gpg_error (GPG_ERR_BAD_DATA);
     277           0 :           continue;
     278             :         }
     279           0 :       p++;
     280           0 :       if ( *p && !spacep (p) )
     281             :         {
     282           0 :           log_error (_("invalid keyflag in '%s', line %d\n"), fname, lnr);
     283           0 :           err = gpg_error (GPG_ERR_BAD_DATA);
     284           0 :           continue;
     285             :         }
     286             : 
     287             :       /* Now check for more key-value pairs of the form NAME[=VALUE]. */
     288           0 :       while (*p)
     289             :         {
     290           0 :           for (; spacep (p); p++)
     291             :             ;
     292           0 :           if (!*p)
     293           0 :             break;
     294           0 :           n = strcspn (p, "= \t");
     295           0 :           if (p[n] == '=')
     296             :             {
     297           0 :               log_error ("assigning a value to a flag is not yet supported; "
     298             :                          "in '%s', line %d\n", fname, lnr);
     299           0 :               err = gpg_error (GPG_ERR_BAD_DATA);
     300           0 :               p++;
     301             :             }
     302           0 :           else if (n == 5 && !memcmp (p, "relax", 5))
     303           0 :             ti->flags.relax = 1;
     304           0 :           else if (n == 2 && !memcmp (p, "cm", 2))
     305           0 :             ti->flags.cm = 1;
     306             :           else
     307           0 :             log_error ("flag '%.*s' in '%s', line %d ignored\n",
     308             :                        n, p, fname, lnr);
     309           0 :           p += n;
     310             :         }
     311           0 :       tableidx++;
     312             :     }
     313           0 :   if ( !err && !es_feof (fp) )
     314             :     {
     315           0 :       err = gpg_error_from_syserror ();
     316           0 :       log_error (_("error reading '%s', line %d: %s\n"),
     317             :                  fname, lnr, gpg_strerror (err));
     318             :     }
     319             : 
     320             :  leave:
     321           0 :   es_fclose (fp);
     322           0 :   *addr_of_table = table;
     323           0 :   *addr_of_tablesize = tablesize;
     324           0 :   *addr_of_tableidx = tableidx;
     325           0 :   return err;
     326             : }
     327             : 
     328             : 
     329             : /* Read the trust files and update the global table on success.  The
     330             :    trusttable is assumed to be locked. */
     331             : static gpg_error_t
     332           0 : read_trustfiles (void)
     333             : {
     334             :   gpg_error_t err;
     335             :   trustitem_t *table, *ti;
     336             :   int tableidx;
     337             :   size_t tablesize;
     338             :   char *fname;
     339           0 :   int allow_include = 1;
     340             : 
     341           0 :   tablesize = 20;
     342           0 :   table = xtrycalloc (tablesize, sizeof *table);
     343           0 :   if (!table)
     344           0 :     return gpg_error_from_syserror ();
     345           0 :   tableidx = 0;
     346             : 
     347           0 :   fname = make_filename_try (gnupg_homedir (), "trustlist.txt", NULL);
     348           0 :   if (!fname)
     349             :     {
     350           0 :       err = gpg_error_from_syserror ();
     351           0 :       xfree (table);
     352           0 :       return err;
     353             :     }
     354             : 
     355           0 :   if ( access (fname, F_OK) )
     356             :     {
     357           0 :       if ( errno == ENOENT )
     358             :         ; /* Silently ignore a non-existing trustfile.  */
     359             :       else
     360             :         {
     361           0 :           err = gpg_error_from_syserror ();
     362           0 :           log_error (_("error opening '%s': %s\n"), fname, gpg_strerror (err));
     363             :         }
     364           0 :       xfree (fname);
     365           0 :       fname = make_filename (gnupg_sysconfdir (), "trustlist.txt", NULL);
     366           0 :       allow_include = 0;
     367             :     }
     368           0 :   err = read_one_trustfile (fname, allow_include,
     369             :                             &table, &tablesize, &tableidx);
     370           0 :   xfree (fname);
     371             : 
     372           0 :   if (err)
     373             :     {
     374           0 :       xfree (table);
     375           0 :       if (gpg_err_code (err) == GPG_ERR_ENOENT)
     376             :         {
     377             :           /* Take a missing trustlist as an empty one.  */
     378           0 :           clear_trusttable ();
     379           0 :           err = 0;
     380             :         }
     381           0 :       return err;
     382             :     }
     383             : 
     384             :   /* Fixme: we should drop duplicates and sort the table. */
     385           0 :   ti = xtryrealloc (table, (tableidx?tableidx:1) * sizeof *table);
     386           0 :   if (!ti)
     387             :     {
     388           0 :       err = gpg_error_from_syserror ();
     389           0 :       xfree (table);
     390           0 :       return err;
     391             :     }
     392             : 
     393             :   /* Replace the trusttable.  */
     394           0 :   xfree (trusttable);
     395           0 :   trusttable = ti;
     396           0 :   trusttablesize = tableidx;
     397           0 :   return 0;
     398             : }
     399             : 
     400             : 
     401             : /* Check whether the given fpr is in our trustdb.  We expect FPR to be
     402             :    an all uppercase hexstring of 40 characters.  If ALREADY_LOCKED is
     403             :    true the function assumes that the trusttable is already locked. */
     404             : static gpg_error_t
     405           0 : istrusted_internal (ctrl_t ctrl, const char *fpr, int *r_disabled,
     406             :                     int already_locked)
     407             : {
     408           0 :   gpg_error_t err = 0;
     409           0 :   int locked = already_locked;
     410             :   trustitem_t *ti;
     411             :   size_t len;
     412             :   unsigned char fprbin[20];
     413             : 
     414           0 :   if (r_disabled)
     415           0 :     *r_disabled = 0;
     416             : 
     417           0 :   if ( hexcolon2bin (fpr, fprbin, 20) < 0 )
     418             :     {
     419           0 :       err = gpg_error (GPG_ERR_INV_VALUE);
     420           0 :       goto leave;
     421             :     }
     422             : 
     423           0 :   if (!already_locked)
     424             :     {
     425           0 :       lock_trusttable ();
     426           0 :       locked = 1;
     427             :     }
     428             : 
     429           0 :   if (!trusttable)
     430             :     {
     431           0 :       err = read_trustfiles ();
     432           0 :       if (err)
     433             :         {
     434           0 :           log_error (_("error reading list of trusted root certificates\n"));
     435           0 :           goto leave;
     436             :         }
     437             :     }
     438             : 
     439           0 :   if (trusttable)
     440             :     {
     441           0 :       for (ti=trusttable, len = trusttablesize; len; ti++, len--)
     442           0 :         if (!memcmp (ti->fpr, fprbin, 20))
     443             :           {
     444           0 :             if (ti->flags.disabled && r_disabled)
     445           0 :               *r_disabled = 1;
     446             : 
     447             :             /* Print status messages only if we have not been called
     448             :                in a locked state.  */
     449           0 :             if (already_locked)
     450             :               ;
     451           0 :             else if (ti->flags.relax)
     452             :               {
     453           0 :                 unlock_trusttable ();
     454           0 :                 locked = 0;
     455           0 :                 err = agent_write_status (ctrl, "TRUSTLISTFLAG", "relax", NULL);
     456             :               }
     457           0 :             else if (ti->flags.cm)
     458             :               {
     459           0 :                 unlock_trusttable ();
     460           0 :                 locked = 0;
     461           0 :                 err = agent_write_status (ctrl, "TRUSTLISTFLAG", "cm", NULL);
     462             :               }
     463             : 
     464           0 :             if (!err)
     465           0 :               err = ti->flags.disabled? gpg_error (GPG_ERR_NOT_TRUSTED) : 0;
     466           0 :             goto leave;
     467             :           }
     468             :     }
     469           0 :   err = gpg_error (GPG_ERR_NOT_TRUSTED);
     470             : 
     471             :  leave:
     472           0 :   if (locked && !already_locked)
     473           0 :     unlock_trusttable ();
     474           0 :   return err;
     475             : }
     476             : 
     477             : 
     478             : /* Check whether the given fpr is in our trustdb.  We expect FPR to be
     479             :    an all uppercase hexstring of 40 characters.  */
     480             : gpg_error_t
     481           0 : agent_istrusted (ctrl_t ctrl, const char *fpr, int *r_disabled)
     482             : {
     483           0 :   return istrusted_internal (ctrl, fpr, r_disabled, 0);
     484             : }
     485             : 
     486             : 
     487             : /* Write all trust entries to FP. */
     488             : gpg_error_t
     489           0 : agent_listtrusted (void *assuan_context)
     490             : {
     491             :   trustitem_t *ti;
     492             :   char key[51];
     493             :   gpg_error_t err;
     494             :   size_t len;
     495             : 
     496           0 :   lock_trusttable ();
     497           0 :   if (!trusttable)
     498             :     {
     499           0 :       err = read_trustfiles ();
     500           0 :       if (err)
     501             :         {
     502           0 :           unlock_trusttable ();
     503           0 :           log_error (_("error reading list of trusted root certificates\n"));
     504           0 :           return err;
     505             :         }
     506             :     }
     507             : 
     508           0 :   if (trusttable)
     509             :     {
     510           0 :       for (ti=trusttable, len = trusttablesize; len; ti++, len--)
     511             :         {
     512           0 :           if (ti->flags.disabled)
     513           0 :             continue;
     514           0 :           bin2hex (ti->fpr, 20, key);
     515           0 :           key[40] = ' ';
     516           0 :           key[41] = ((ti->flags.for_smime && ti->flags.for_pgp)? '*'
     517           0 :                      : ti->flags.for_smime? 'S': ti->flags.for_pgp? 'P':' ');
     518           0 :           key[42] = '\n';
     519           0 :           assuan_send_data (assuan_context, key, 43);
     520           0 :           assuan_send_data (assuan_context, NULL, 0); /* flush */
     521             :         }
     522             :     }
     523             : 
     524           0 :   unlock_trusttable ();
     525           0 :   return 0;
     526             : }
     527             : 
     528             : 
     529             : /* Create a copy of string with colons inserted after each two bytes.
     530             :    Caller needs to release the string.  In case of a memory failure,
     531             :    NULL is returned.  */
     532             : static char *
     533           0 : insert_colons (const char *string)
     534             : {
     535             :   char *buffer, *p;
     536           0 :   size_t n = strlen (string);
     537           0 :   size_t nnew = n + (n+1)/2;
     538             : 
     539           0 :   p = buffer = xtrymalloc ( nnew + 1 );
     540           0 :   if (!buffer)
     541           0 :     return NULL;
     542           0 :   while (*string)
     543             :     {
     544           0 :       *p++ = *string++;
     545           0 :       if (*string)
     546             :         {
     547           0 :           *p++ = *string++;
     548           0 :           if (*string)
     549           0 :             *p++ = ':';
     550             :         }
     551             :     }
     552           0 :   *p = 0;
     553           0 :   assert (strlen (buffer) <= nnew);
     554             : 
     555           0 :   return buffer;
     556             : }
     557             : 
     558             : 
     559             : /* To pretty print DNs in the Pinentry, we replace slashes by
     560             :    REPLSTRING.  The caller needs to free the returned string.  NULL is
     561             :    returned on error with ERRNO set.  */
     562             : static char *
     563           0 : reformat_name (const char *name, const char *replstring)
     564             : {
     565             :   const char *s;
     566             :   char *newname;
     567             :   char *d;
     568             :   size_t count;
     569           0 :   size_t replstringlen = strlen (replstring);
     570             : 
     571             :   /* If the name does not start with a slash it is not a preformatted
     572             :      DN and thus we don't bother to reformat it.  */
     573           0 :   if (*name != '/')
     574           0 :     return xtrystrdup (name);
     575             : 
     576             :   /* Count the names.  Note that a slash contained in a DN part is
     577             :      expected to be C style escaped and thus the slashes we see here
     578             :      are the actual part delimiters.  */
     579           0 :   for (s=name+1, count=0; *s; s++)
     580           0 :     if (*s == '/')
     581           0 :       count++;
     582           0 :   newname = xtrymalloc (strlen (name) + count*replstringlen + 1);
     583           0 :   if (!newname)
     584           0 :     return NULL;
     585           0 :   for (s=name+1, d=newname; *s; s++)
     586           0 :     if (*s == '/')
     587           0 :       d = stpcpy (d, replstring);
     588             :     else
     589           0 :       *d++ = *s;
     590           0 :   *d = 0;
     591           0 :   return newname;
     592             : }
     593             : 
     594             : 
     595             : /* Insert the given fpr into our trustdb.  We expect FPR to be an all
     596             :    uppercase hexstring of 40 characters. FLAG is either 'P' or 'C'.
     597             :    This function does first check whether that key has already been
     598             :    put into the trustdb and returns success in this case.  Before a
     599             :    FPR actually gets inserted, the user is asked by means of the
     600             :    Pinentry whether this is actual what he wants to do.  */
     601             : gpg_error_t
     602           0 : agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag)
     603             : {
     604           0 :   gpg_error_t err = 0;
     605             :   char *desc;
     606             :   char *fname;
     607             :   estream_t fp;
     608             :   char *fprformatted;
     609             :   char *nameformatted;
     610             :   int is_disabled;
     611             :   int yes_i_trust;
     612             : 
     613             :   /* Check whether we are at all allowed to modify the trustlist.
     614             :      This is useful so that the trustlist may be a symlink to a global
     615             :      trustlist with only admin priviliges to modify it.  Of course
     616             :      this is not a secure way of denying access, but it avoids the
     617             :      usual clicking on an Okay button most users are used to. */
     618           0 :   fname = make_filename_try (gnupg_homedir (), "trustlist.txt", NULL);
     619           0 :   if (!fname)
     620           0 :     return gpg_error_from_syserror ();
     621             : 
     622           0 :   if ( access (fname, W_OK) && errno != ENOENT)
     623             :     {
     624           0 :       xfree (fname);
     625           0 :       return gpg_error (GPG_ERR_EPERM);
     626             :     }
     627           0 :   xfree (fname);
     628             : 
     629           0 :   if (!agent_istrusted (ctrl, fpr, &is_disabled))
     630             :     {
     631           0 :       return 0; /* We already got this fingerprint.  Silently return
     632             :                    success. */
     633             :     }
     634             : 
     635             :   /* This feature must explicitly been enabled. */
     636           0 :   if (!opt.allow_mark_trusted)
     637           0 :     return gpg_error (GPG_ERR_NOT_SUPPORTED);
     638             : 
     639           0 :   if (is_disabled)
     640             :     {
     641             :       /* There is an disabled entry in the trustlist.  Return an error
     642             :          so that the user won't be asked again for that one.  Changing
     643             :          this flag with the integrated marktrusted feature is and will
     644             :          not be made possible.  */
     645           0 :       return gpg_error (GPG_ERR_NOT_TRUSTED);
     646             :     }
     647             : 
     648             : 
     649             :   /* Insert a new one. */
     650           0 :   nameformatted = reformat_name (name, "%0A   ");
     651           0 :   if (!nameformatted)
     652           0 :     return gpg_error_from_syserror ();
     653             : 
     654             :   /* First a general question whether this is trusted.  */
     655           0 :   desc = xtryasprintf (
     656             :                 /* TRANSLATORS: This prompt is shown by the Pinentry
     657             :                    and has one special property: A "%%0A" is used by
     658             :                    Pinentry to insert a line break.  The double
     659             :                    percent sign is actually needed because it is also
     660             :                    a printf format string.  If you need to insert a
     661             :                    plain % sign, you need to encode it as "%%25".  The
     662             :                    "%s" gets replaced by the name as stored in the
     663             :                    certificate. */
     664             :                 L_("Do you ultimately trust%%0A"
     665             :                    "  \"%s\"%%0A"
     666             :                    "to correctly certify user certificates?"),
     667             :                 nameformatted);
     668           0 :   if (!desc)
     669             :     {
     670           0 :       xfree (nameformatted);
     671           0 :       return out_of_core ();
     672             :     }
     673           0 :   err = agent_get_confirmation (ctrl, desc, L_("Yes"), L_("No"), 1);
     674           0 :   xfree (desc);
     675           0 :   if (!err)
     676           0 :     yes_i_trust = 1;
     677           0 :   else if (gpg_err_code (err) == GPG_ERR_NOT_CONFIRMED)
     678           0 :     yes_i_trust = 0;
     679             :   else
     680             :     {
     681           0 :       xfree (nameformatted);
     682           0 :       return err;
     683             :     }
     684             : 
     685             : 
     686           0 :   fprformatted = insert_colons (fpr);
     687           0 :   if (!fprformatted)
     688             :     {
     689           0 :       xfree (nameformatted);
     690           0 :       return out_of_core ();
     691             :     }
     692             : 
     693             :   /* If the user trusts this certificate he has to verify the
     694             :      fingerprint of course.  */
     695           0 :   if (yes_i_trust)
     696             :     {
     697           0 :       desc = xtryasprintf
     698             :         (
     699             :          /* TRANSLATORS: This prompt is shown by the Pinentry and has
     700             :             one special property: A "%%0A" is used by Pinentry to
     701             :             insert a line break.  The double percent sign is actually
     702             :             needed because it is also a printf format string.  If you
     703             :             need to insert a plain % sign, you need to encode it as
     704             :             "%%25".  The second "%s" gets replaced by a hexdecimal
     705             :             fingerprint string whereas the first one receives the name
     706             :             as stored in the certificate. */
     707             :          L_("Please verify that the certificate identified as:%%0A"
     708             :             "  \"%s\"%%0A"
     709             :             "has the fingerprint:%%0A"
     710             :             "  %s"), nameformatted, fprformatted);
     711           0 :       if (!desc)
     712             :         {
     713           0 :           xfree (fprformatted);
     714           0 :           xfree (nameformatted);
     715           0 :           return out_of_core ();
     716             :         }
     717             : 
     718             :       /* TRANSLATORS: "Correct" is the label of a button and intended
     719             :          to be hit if the fingerprint matches the one of the CA.  The
     720             :          other button is "the default "Cancel" of the Pinentry. */
     721           0 :       err = agent_get_confirmation (ctrl, desc, L_("Correct"), L_("Wrong"), 1);
     722           0 :       xfree (desc);
     723           0 :       if (gpg_err_code (err) == GPG_ERR_NOT_CONFIRMED)
     724           0 :         yes_i_trust = 0;
     725           0 :       else if (err)
     726             :         {
     727           0 :           xfree (fprformatted);
     728           0 :           xfree (nameformatted);
     729           0 :           return err;
     730             :         }
     731             :     }
     732             : 
     733             : 
     734             :   /* Now check again to avoid duplicates.  We take the lock to make
     735             :      sure that nobody else plays with our file and force a reread.  */
     736           0 :   lock_trusttable ();
     737           0 :   clear_trusttable ();
     738           0 :   if (!istrusted_internal (ctrl, fpr, &is_disabled, 1) || is_disabled)
     739             :     {
     740           0 :       unlock_trusttable ();
     741           0 :       xfree (fprformatted);
     742           0 :       xfree (nameformatted);
     743           0 :       return is_disabled? gpg_error (GPG_ERR_NOT_TRUSTED) : 0;
     744             :     }
     745             : 
     746           0 :   fname = make_filename_try (gnupg_homedir (), "trustlist.txt", NULL);
     747           0 :   if (!fname)
     748             :     {
     749           0 :       err = gpg_error_from_syserror ();
     750           0 :       unlock_trusttable ();
     751           0 :       xfree (fprformatted);
     752           0 :       xfree (nameformatted);
     753           0 :       return err;
     754             :     }
     755           0 :   if ( access (fname, F_OK) && errno == ENOENT)
     756             :     {
     757           0 :       fp = es_fopen (fname, "wx,mode=-rw-r");
     758           0 :       if (!fp)
     759             :         {
     760           0 :           err = gpg_error_from_syserror ();
     761           0 :           log_error ("can't create '%s': %s\n", fname, gpg_strerror (err));
     762           0 :           xfree (fname);
     763           0 :           unlock_trusttable ();
     764           0 :           xfree (fprformatted);
     765           0 :           xfree (nameformatted);
     766           0 :           return err;
     767             :         }
     768           0 :       es_fputs (headerblurb, fp);
     769           0 :       es_fclose (fp);
     770             :     }
     771           0 :   fp = es_fopen (fname, "a+,mode=-rw-r");
     772           0 :   if (!fp)
     773             :     {
     774           0 :       err = gpg_error_from_syserror ();
     775           0 :       log_error ("can't open '%s': %s\n", fname, gpg_strerror (err));
     776           0 :       xfree (fname);
     777           0 :       unlock_trusttable ();
     778           0 :       xfree (fprformatted);
     779           0 :       xfree (nameformatted);
     780           0 :       return err;
     781             :     }
     782             : 
     783             :   /* Append the key. */
     784           0 :   es_fputs ("\n# ", fp);
     785           0 :   xfree (nameformatted);
     786           0 :   nameformatted = reformat_name (name, "\n# ");
     787           0 :   if (!nameformatted || strchr (name, '\n'))
     788             :     {
     789             :       /* Note that there should never be a LF in NAME but we better
     790             :          play safe and print a sanitized version in this case.  */
     791           0 :       es_write_sanitized (fp, name, strlen (name), NULL, NULL);
     792             :     }
     793             :   else
     794           0 :     es_fputs (nameformatted, fp);
     795           0 :   es_fprintf (fp, "\n%s%s %c%s\n", yes_i_trust?"":"!", fprformatted, flag,
     796             :               flag == 'S'? " relax":"");
     797           0 :   if (es_ferror (fp))
     798           0 :     err = gpg_error_from_syserror ();
     799             : 
     800           0 :   if (es_fclose (fp))
     801           0 :     err = gpg_error_from_syserror ();
     802             : 
     803           0 :   clear_trusttable ();
     804           0 :   xfree (fname);
     805           0 :   unlock_trusttable ();
     806           0 :   xfree (fprformatted);
     807           0 :   xfree (nameformatted);
     808           0 :   if (!err)
     809           0 :     bump_key_eventcounter ();
     810           0 :   return err;
     811             : }
     812             : 
     813             : 
     814             : /* This function may be called to force reloading of the
     815             :    trustlist.  */
     816             : void
     817           0 : agent_reload_trustlist (void)
     818             : {
     819             :   /* All we need to do is to delete the trusttable.  At the next
     820             :      access it will get re-read. */
     821           0 :   lock_trusttable ();
     822           0 :   clear_trusttable ();
     823           0 :   unlock_trusttable ();
     824           0 :   bump_key_eventcounter ();
     825           0 : }

Generated by: LCOV version 1.11