LCOV - code coverage report
Current view: top level - tests/openpgp - fake-pinentry.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 99 118 83.9 %
Date: 2016-09-12 13:01:59 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /* Fake pinentry program for the OpenPGP test suite.
       2             :  *
       3             :  * Copyright (C) 2016 g10 code GmbH
       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 <stdlib.h>
      22             : #include <stdio.h>
      23             : #include <string.h>
      24             : #include <stdarg.h>
      25             : 
      26             : FILE *log_stream;
      27             : 
      28             : int
      29         223 : reply (const char *fmt, ...)
      30             : {
      31             :   int result;
      32             :   va_list ap;
      33             : 
      34         223 :   if (log_stream)
      35             :     {
      36          23 :       fprintf (log_stream, "> ");
      37          23 :       va_start (ap, fmt);
      38          23 :       vfprintf (log_stream, fmt, ap);
      39          23 :       va_end (ap);
      40             :     }
      41         223 :   va_start (ap, fmt);
      42         223 :   result = vprintf (fmt, ap);
      43         223 :   va_end (ap);
      44             : 
      45         223 :   return result;
      46             : }
      47             : 
      48             : /* Return the first line from FNAME, removing it from the file.  */
      49             : char *
      50           1 : get_passphrase (const char *fname)
      51             : {
      52           1 :   char *passphrase = NULL;
      53             :   size_t fname_len;
      54             :   char *fname_new;
      55             :   FILE *source, *sink;
      56             :   char linebuf[80];
      57             : 
      58           1 :   fname_len = strlen (fname);
      59           1 :   fname_new = malloc (fname_len + 5);
      60           1 :   if (fname_new == NULL)
      61             :     {
      62           0 :       perror ("malloc");
      63           0 :       exit (1);
      64             :     }
      65           1 :   snprintf (fname_new, fname_len + 5, "%s.new", fname);
      66             : 
      67           1 :   source = fopen (fname, "r");
      68           1 :   if (! source)
      69             :     {
      70           0 :       perror (fname);
      71           0 :       exit (1);
      72             :     }
      73             : 
      74           1 :   sink = fopen (fname_new, "w");
      75           1 :   if (! sink)
      76             :     {
      77           0 :       perror (fname_new);
      78           0 :       exit (1);
      79             :     }
      80             : 
      81           3 :   while (fgets (linebuf, sizeof linebuf, source))
      82             :     {
      83           1 :       linebuf[sizeof linebuf - 1] = 0;
      84           1 :       if (passphrase == NULL)
      85             :         {
      86           1 :           passphrase = strdup (linebuf);
      87           1 :           if (passphrase == NULL)
      88             :             {
      89           0 :               perror ("strdup");
      90           0 :               exit (1);
      91             :             }
      92             :         }
      93             :       else
      94           0 :         fputs (linebuf, sink);
      95             :     }
      96             : 
      97           1 :   if (ferror (source))
      98             :     {
      99           0 :       perror (fname);
     100           0 :       exit (1);
     101             :     }
     102             : 
     103           1 :   if (ferror (sink))
     104             :     {
     105           0 :       perror (fname_new);
     106           0 :       exit (1);
     107             :     }
     108             : 
     109           1 :   fclose (source);
     110           1 :   fclose (sink);
     111           1 :   rename (fname_new, fname);
     112           1 :   return passphrase;
     113             : }
     114             : 
     115             : 
     116             : #define spacep(p)   (*(p) == ' ' || *(p) == '\t')
     117             : 
     118             : /* Skip over options in LINE.
     119             : 
     120             :    Blanks after the options are also removed.  Options are indicated
     121             :    by two leading dashes followed by a string consisting of non-space
     122             :    characters.  The special option "--" indicates an explicit end of
     123             :    options; all what follows will not be considered an option.  The
     124             :    first no-option string also indicates the end of option parsing. */
     125             : char *
     126          10 : skip_options (const char *line)
     127             : {
     128          20 :   while (spacep (line))
     129           0 :     line++;
     130          23 :   while (*line == '-' && line[1] == '-')
     131             :     {
     132         126 :       while (*line && !spacep (line))
     133         120 :         line++;
     134           7 :       while (spacep (line))
     135           1 :         line++;
     136             :     }
     137          10 :   return (char*) line;
     138             : }
     139             : 
     140             : 
     141             : /* Return a pointer to the argument of the option with NAME.  If such
     142             :    an option is not given, NULL is returned. */
     143             : char *
     144          18 : option_value (const char *line, const char *name)
     145             : {
     146             :   char *s;
     147          18 :   int n = strlen (name);
     148             : 
     149          18 :   s = strstr (line, name);
     150          18 :   if (s && s >= skip_options (line))
     151           0 :     return NULL;
     152          18 :   if (s && (s == line || spacep (s-1))
     153           2 :       && s[n] && (spacep (s+n) || s[n] == '='))
     154             :     {
     155           2 :       s += n + 1;
     156           2 :       s += strspn (s, " ");
     157           2 :       if (*s && !spacep(s))
     158           2 :         return s;
     159             :     }
     160          16 :   return NULL;
     161             : }
     162             : 
     163             : int
     164           9 : main (int argc, char **argv)
     165             : {
     166             :   char *args;
     167             :   char *logfile;
     168             :   char *passphrasefile;
     169             :   char *passphrase;
     170             : 
     171             :   /* We get our options via PINENTRY_USER_DATA.  */
     172             :   (void) argc, (void) argv;
     173             : 
     174           9 :   setvbuf (stdin, NULL, _IOLBF, BUFSIZ);
     175           9 :   setvbuf (stdout, NULL, _IOLBF, BUFSIZ);
     176             : 
     177           9 :   args = getenv ("PINENTRY_USER_DATA");
     178           9 :   if (! args)
     179           8 :     args = "";
     180             : 
     181           9 :   logfile = option_value (args, "--logfile");
     182           9 :   if (logfile)
     183             :     {
     184           1 :       char *p = logfile, more;
     185          28 :       while (*p && ! spacep (p))
     186          26 :         p++;
     187           1 :       more = !! *p;
     188           1 :       *p = 0;
     189           1 :       args = more ? p+1 : p;
     190             : 
     191           1 :       log_stream = fopen (logfile, "a");
     192           1 :       if (! log_stream)
     193             :         {
     194           0 :           perror (logfile);
     195           0 :           return 1;
     196             :         }
     197             :     }
     198             : 
     199           9 :   passphrasefile = option_value (args, "--passphrasefile");
     200           9 :   if (passphrasefile)
     201             :     {
     202           1 :       char *p = passphrasefile, more;
     203          27 :       while (*p && ! spacep (p))
     204          25 :         p++;
     205           1 :       more = !! *p;
     206           1 :       *p = 0;
     207           1 :       args = more ? p+1 : p;
     208             : 
     209           1 :       passphrase = get_passphrase (passphrasefile);
     210           1 :       if (! passphrase)
     211             :         {
     212           0 :           reply ("# Passphrasefile '%s' is empty.  Terminating.\n",
     213             :                  passphrasefile);
     214           0 :           return 1;
     215             :         }
     216             : 
     217           1 :       p = passphrase + strlen (passphrase) - 1;
     218           1 :       if (*p == '\n')
     219           1 :         *p = 0;
     220             :     }
     221             :   else
     222             :     {
     223           8 :       passphrase = skip_options (args);
     224           8 :       if (*passphrase == 0)
     225           8 :         passphrase = "no PINENTRY_USER_DATA -- using default passphrase";
     226             :     }
     227             : 
     228           9 :   reply ("# fake-pinentry started.  Passphrase='%s'.\n", passphrase);
     229           9 :   reply ("OK - what's up?\n");
     230             : 
     231           9 :   while (! feof (stdin))
     232             :     {
     233             :       char buffer[1024];
     234             : 
     235         187 :       if (fgets (buffer, sizeof buffer, stdin) == NULL)
     236           9 :         break;
     237             : 
     238         187 :       if (log_stream)
     239          19 :         fprintf (log_stream, "< %s", buffer);
     240             : 
     241         187 :       if (strncmp (buffer, "GETPIN", 6) == 0)
     242           9 :         reply ("D %s\n", passphrase);
     243         178 :       else if (strncmp (buffer, "BYE", 3) == 0)
     244             :         {
     245           9 :           reply ("OK\n");
     246           9 :           break;
     247             :         }
     248             : 
     249         178 :       reply ("OK\n");
     250             :     }
     251             : 
     252           9 :   reply ("# Connection terminated.\n");
     253           9 :   if (log_stream)
     254           1 :     fclose (log_stream);
     255             : 
     256           9 :   return 0;
     257             : }

Generated by: LCOV version 1.11