LCOV - code coverage report
Current view: top level - agent - call-scd.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 84 500 16.8 %
Date: 2016-09-12 12:29:17 Functions: 6 27 22.2 %

          Line data    Source code
       1             : /* call-scd.c - fork of the scdaemon to do SC operations
       2             :  * Copyright (C) 2001, 2002, 2005, 2007, 2010,
       3             :  *               2011 Free Software Foundation, Inc.
       4             :  * Copyright (C) 2013 Werner Koch
       5             :  *
       6             :  * This file is part of GnuPG.
       7             :  *
       8             :  * GnuPG is free software; you can redistribute it and/or modify
       9             :  * it under the terms of the GNU General Public License as published by
      10             :  * the Free Software Foundation; either version 3 of the License, or
      11             :  * (at your option) any later version.
      12             :  *
      13             :  * GnuPG is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  * GNU General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU General Public License
      19             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #include <config.h>
      23             : #include <errno.h>
      24             : #include <stdio.h>
      25             : #include <stdlib.h>
      26             : #include <string.h>
      27             : #include <ctype.h>
      28             : #include <assert.h>
      29             : #include <unistd.h>
      30             : #ifdef HAVE_SIGNAL_H
      31             : # include <signal.h>
      32             : #endif
      33             : #include <sys/stat.h>
      34             : #include <sys/types.h>
      35             : #ifndef HAVE_W32_SYSTEM
      36             : #include <sys/wait.h>
      37             : #endif
      38             : #include <npth.h>
      39             : 
      40             : #include "agent.h"
      41             : #include <assuan.h>
      42             : 
      43             : #ifdef _POSIX_OPEN_MAX
      44             : #define MAX_OPEN_FDS _POSIX_OPEN_MAX
      45             : #else
      46             : #define MAX_OPEN_FDS 20
      47             : #endif
      48             : 
      49             : /* Definition of module local data of the CTRL structure.  */
      50             : struct scd_local_s
      51             : {
      52             :   /* We keep a list of all allocated context with a an achnor at
      53             :      SCD_LOCAL_LIST (see below). */
      54             :   struct scd_local_s *next_local;
      55             : 
      56             :   /* We need to get back to the ctrl object actually referencing this
      57             :      structure.  This is really an awkward way of enumerint the lcoal
      58             :      contects.  A much cleaner way would be to keep a global list of
      59             :      ctrl objects to enumerate them.  */
      60             :   ctrl_t ctrl_backlink;
      61             : 
      62             :   assuan_context_t ctx; /* NULL or session context for the SCdaemon
      63             :                            used with this connection. */
      64             :   int locked;           /* This flag is used to assert proper use of
      65             :                            start_scd and unlock_scd. */
      66             : 
      67             : };
      68             : 
      69             : 
      70             : /* Callback parameter for learn card */
      71             : struct learn_parm_s
      72             : {
      73             :   void (*kpinfo_cb)(void*, const char *);
      74             :   void *kpinfo_cb_arg;
      75             :   void (*certinfo_cb)(void*, const char *);
      76             :   void *certinfo_cb_arg;
      77             :   void (*sinfo_cb)(void*, const char *, size_t, const char *);
      78             :   void *sinfo_cb_arg;
      79             : };
      80             : 
      81             : struct inq_needpin_s
      82             : {
      83             :   assuan_context_t ctx;
      84             :   int (*getpin_cb)(void *, const char *, char*, size_t);
      85             :   void *getpin_cb_arg;
      86             :   assuan_context_t passthru;  /* If not NULL, pass unknown inquiries
      87             :                                  up to the caller.  */
      88             :   int any_inq_seen;
      89             : };
      90             : 
      91             : 
      92             : /* To keep track of all active SCD contexts, we keep a linked list
      93             :    anchored at this variable. */
      94             : static struct scd_local_s *scd_local_list;
      95             : 
      96             : /* A Mutex used inside the start_scd function. */
      97             : static npth_mutex_t start_scd_lock;
      98             : 
      99             : /* A malloced string with the name of the socket to be used for
     100             :    additional connections.  May be NULL if not provided by
     101             :    SCdaemon. */
     102             : static char *socket_name;
     103             : 
     104             : /* The context of the primary connection.  This is also used as a flag
     105             :    to indicate whether the scdaemon has been started. */
     106             : static assuan_context_t primary_scd_ctx;
     107             : 
     108             : /* To allow reuse of the primary connection, the following flag is set
     109             :    to true if the primary context has been reset and is not in use by
     110             :    any connection. */
     111             : static int primary_scd_ctx_reusable;
     112             : 
     113             : 
     114             : 
     115             : /* Local prototypes.  */
     116             : 
     117             : 
     118             : 
     119             : 
     120             : /* This function must be called once to initialize this module.  This
     121             :    has to be done before a second thread is spawned.  We can't do the
     122             :    static initialization because NPth emulation code might not be able
     123             :    to do a static init; in particular, it is not possible for W32. */
     124             : void
     125          48 : initialize_module_call_scd (void)
     126             : {
     127             :   static int initialized;
     128             :   int err;
     129             : 
     130          48 :   if (!initialized)
     131             :     {
     132          48 :       err = npth_mutex_init (&start_scd_lock, NULL);
     133          48 :       if (err)
     134           0 :         log_fatal ("error initializing mutex: %s\n", strerror (err));
     135          48 :       initialized = 1;
     136             :     }
     137          48 : }
     138             : 
     139             : 
     140             : /* This function may be called to print infromation pertaining to the
     141             :    current state of this module to the log. */
     142             : void
     143           0 : agent_scd_dump_state (void)
     144             : {
     145           0 :   log_info ("agent_scd_dump_state: primary_scd_ctx=%p pid=%ld reusable=%d\n",
     146             :             primary_scd_ctx,
     147           0 :             (long)assuan_get_pid (primary_scd_ctx),
     148             :             primary_scd_ctx_reusable);
     149           0 :   if (socket_name)
     150           0 :     log_info ("agent_scd_dump_state: socket='%s'\n", socket_name);
     151           0 : }
     152             : 
     153             : 
     154             : /* The unlock_scd function shall be called after having accessed the
     155             :    SCD.  It is currently not very useful but gives an opportunity to
     156             :    keep track of connections currently calling SCD.  Note that the
     157             :    "lock" operation is done by the start_scd() function which must be
     158             :    called and error checked before any SCD operation.  CTRL is the
     159             :    usual connection context and RC the error code to be passed trhough
     160             :    the function. */
     161             : static int
     162           5 : unlock_scd (ctrl_t ctrl, int rc)
     163             : {
     164           5 :   if (ctrl->scd_local->locked != 1)
     165             :     {
     166           0 :       log_error ("unlock_scd: invalid lock count (%d)\n",
     167           0 :                  ctrl->scd_local->locked);
     168           0 :       if (!rc)
     169           0 :         rc = gpg_error (GPG_ERR_INTERNAL);
     170             :     }
     171           5 :   ctrl->scd_local->locked = 0;
     172           5 :   return rc;
     173             : }
     174             : 
     175             : /* To make sure we leave no secrets in our image after forking of the
     176             :    scdaemon, we use this callback. */
     177             : static void
     178           0 : atfork_cb (void *opaque, int where)
     179             : {
     180             :   (void)opaque;
     181             : 
     182           0 :   if (!where)
     183           0 :     gcry_control (GCRYCTL_TERM_SECMEM);
     184           0 : }
     185             : 
     186             : 
     187             : /* Fork off the SCdaemon if this has not already been done.  Lock the
     188             :    daemon and make sure that a proper context has been setup in CTRL.
     189             :    This function might also lock the daemon, which means that the
     190             :    caller must call unlock_scd after this function has returned
     191             :    success and the actual Assuan transaction been done. */
     192             : static int
     193           5 : start_scd (ctrl_t ctrl)
     194             : {
     195           5 :   gpg_error_t err = 0;
     196             :   const char *pgmname;
     197           5 :   assuan_context_t ctx = NULL;
     198             :   const char *argv[5];
     199             :   assuan_fd_t no_close_list[3];
     200             :   int i;
     201             :   int rc;
     202           5 :   char *abs_homedir = NULL;
     203             : 
     204           5 :   if (opt.disable_scdaemon)
     205           0 :     return gpg_error (GPG_ERR_NOT_SUPPORTED);
     206             : 
     207             :   /* If this is the first call for this session, setup the local data
     208             :      structure. */
     209           5 :   if (!ctrl->scd_local)
     210             :     {
     211           5 :       ctrl->scd_local = xtrycalloc (1, sizeof *ctrl->scd_local);
     212           5 :       if (!ctrl->scd_local)
     213           0 :         return gpg_error_from_syserror ();
     214           5 :       ctrl->scd_local->ctrl_backlink = ctrl;
     215           5 :       ctrl->scd_local->next_local = scd_local_list;
     216           5 :       scd_local_list = ctrl->scd_local;
     217             :     }
     218             : 
     219             : 
     220             :   /* Assert that the lock count is as expected. */
     221           5 :   if (ctrl->scd_local->locked)
     222             :     {
     223           0 :       log_error ("start_scd: invalid lock count (%d)\n",
     224           0 :                  ctrl->scd_local->locked);
     225           0 :       return gpg_error (GPG_ERR_INTERNAL);
     226             :     }
     227           5 :   ctrl->scd_local->locked++;
     228             : 
     229           5 :   if (ctrl->scd_local->ctx)
     230           0 :     return 0; /* Okay, the context is fine.  We used to test for an
     231             :                  alive context here and do an disconnect.  Now that we
     232             :                  have a ticker function to check for it, it is easier
     233             :                  not to check here but to let the connection run on an
     234             :                  error instead. */
     235             : 
     236             : 
     237             :   /* We need to protect the following code. */
     238           5 :   rc = npth_mutex_lock (&start_scd_lock);
     239           5 :   if (rc)
     240             :     {
     241           0 :       log_error ("failed to acquire the start_scd lock: %s\n",
     242             :                  strerror (rc));
     243           0 :       return gpg_error (GPG_ERR_INTERNAL);
     244             :     }
     245             : 
     246             :   /* Check whether the pipe server has already been started and in
     247             :      this case either reuse a lingering pipe connection or establish a
     248             :      new socket based one. */
     249           5 :   if (primary_scd_ctx && primary_scd_ctx_reusable)
     250             :     {
     251           0 :       ctx = primary_scd_ctx;
     252           0 :       primary_scd_ctx_reusable = 0;
     253           0 :       if (opt.verbose)
     254           0 :         log_info ("new connection to SCdaemon established (reusing)\n");
     255           0 :       goto leave;
     256             :     }
     257             : 
     258           5 :   rc = assuan_new (&ctx);
     259           5 :   if (rc)
     260             :     {
     261           0 :       log_error ("can't allocate assuan context: %s\n", gpg_strerror (rc));
     262           0 :       err = rc;
     263           0 :       goto leave;
     264             :     }
     265             : 
     266           5 :   if (socket_name)
     267             :     {
     268           0 :       rc = assuan_socket_connect (ctx, socket_name, 0, 0);
     269           0 :       if (rc)
     270             :         {
     271           0 :           log_error ("can't connect to socket '%s': %s\n",
     272             :                      socket_name, gpg_strerror (rc));
     273           0 :           err = gpg_error (GPG_ERR_NO_SCDAEMON);
     274           0 :           goto leave;
     275             :         }
     276             : 
     277           0 :       if (opt.verbose)
     278           0 :         log_info ("new connection to SCdaemon established\n");
     279           0 :       goto leave;
     280             :     }
     281             : 
     282           5 :   if (primary_scd_ctx)
     283             :     {
     284           0 :       log_info ("SCdaemon is running but won't accept further connections\n");
     285           0 :       err = gpg_error (GPG_ERR_NO_SCDAEMON);
     286           0 :       goto leave;
     287             :     }
     288             : 
     289             :   /* Nope, it has not been started.  Fire it up now. */
     290           5 :   if (opt.verbose)
     291           0 :     log_info ("no running SCdaemon - starting it\n");
     292             : 
     293           5 :   if (fflush (NULL))
     294             :     {
     295             : #ifndef HAVE_W32_SYSTEM
     296           0 :       err = gpg_error_from_syserror ();
     297             : #endif
     298           0 :       log_error ("error flushing pending output: %s\n", strerror (errno));
     299             :       /* At least Windows XP fails here with EBADF.  According to docs
     300             :          and Wine an fflush(NULL) is the same as _flushall.  However
     301             :          the Wime implementaion does not flush stdin,stdout and stderr
     302             :          - see above.  Lets try to ignore the error. */
     303             : #ifndef HAVE_W32_SYSTEM
     304           0 :       goto leave;
     305             : #endif
     306             :     }
     307             : 
     308           5 :   if (!opt.scdaemon_program || !*opt.scdaemon_program)
     309           1 :     opt.scdaemon_program = gnupg_module_name (GNUPG_MODULE_NAME_SCDAEMON);
     310           5 :   if ( !(pgmname = strrchr (opt.scdaemon_program, '/')))
     311           0 :     pgmname = opt.scdaemon_program;
     312             :   else
     313           5 :     pgmname++;
     314             : 
     315           5 :   argv[0] = pgmname;
     316           5 :   argv[1] = "--multi-server";
     317           5 :   if (gnupg_default_homedir_p ())
     318           0 :     argv[2] = NULL;
     319             :   else
     320             :     {
     321           5 :       abs_homedir = make_absfilename_try (gnupg_homedir (), NULL);
     322           5 :       if (!abs_homedir)
     323             :         {
     324           0 :           log_error ("error building filename: %s\n",
     325             :                      gpg_strerror (gpg_error_from_syserror ()));
     326           0 :           goto leave;
     327             :         }
     328             : 
     329           5 :       argv[2] = "--homedir";
     330           5 :       argv[3] = abs_homedir;
     331           5 :       argv[4] = NULL;
     332             :     }
     333             : 
     334           5 :   i=0;
     335           5 :   if (!opt.running_detached)
     336             :     {
     337           0 :       if (log_get_fd () != -1)
     338           0 :         no_close_list[i++] = assuan_fd_from_posix_fd (log_get_fd ());
     339           0 :       no_close_list[i++] = assuan_fd_from_posix_fd (fileno (stderr));
     340             :     }
     341           5 :   no_close_list[i] = ASSUAN_INVALID_FD;
     342             : 
     343             :   /* Connect to the scdaemon and perform initial handshaking.  Use
     344             :      detached flag so that under Windows SCDAEMON does not show up a
     345             :      new window.  */
     346           5 :   rc = assuan_pipe_connect (ctx, opt.scdaemon_program, argv,
     347             :                             no_close_list, atfork_cb, NULL,
     348             :                             ASSUAN_PIPE_CONNECT_DETACHED);
     349           5 :   if (rc)
     350             :     {
     351           5 :       log_error ("can't connect to the SCdaemon: %s\n",
     352             :                  gpg_strerror (rc));
     353           5 :       err = gpg_error (GPG_ERR_NO_SCDAEMON);
     354           5 :       goto leave;
     355             :     }
     356             : 
     357           0 :   if (opt.verbose)
     358           0 :     log_debug ("first connection to SCdaemon established\n");
     359             : 
     360             : 
     361             :   /* Get the name of the additional socket opened by scdaemon. */
     362             :   {
     363             :     membuf_t data;
     364             :     unsigned char *databuf;
     365             :     size_t datalen;
     366             : 
     367           0 :     xfree (socket_name);
     368           0 :     socket_name = NULL;
     369           0 :     init_membuf (&data, 256);
     370           0 :     assuan_transact (ctx, "GETINFO socket_name",
     371             :                      put_membuf_cb, &data, NULL, NULL, NULL, NULL);
     372             : 
     373           0 :     databuf = get_membuf (&data, &datalen);
     374           0 :     if (databuf && datalen)
     375             :       {
     376           0 :         socket_name = xtrymalloc (datalen + 1);
     377           0 :         if (!socket_name)
     378           0 :           log_error ("warning: can't store socket name: %s\n",
     379           0 :                      strerror (errno));
     380             :         else
     381             :           {
     382           0 :             memcpy (socket_name, databuf, datalen);
     383           0 :             socket_name[datalen] = 0;
     384           0 :             if (DBG_IPC)
     385           0 :               log_debug ("additional connections at '%s'\n", socket_name);
     386             :           }
     387             :       }
     388           0 :     xfree (databuf);
     389             :   }
     390             : 
     391             :   /* Tell the scdaemon we want him to send us an event signal.  We
     392             :      don't support this for W32CE.  */
     393             : #ifndef HAVE_W32CE_SYSTEM
     394           0 :   if (opt.sigusr2_enabled)
     395             :     {
     396             :       char buf[100];
     397             : 
     398             : #ifdef HAVE_W32_SYSTEM
     399             :       snprintf (buf, sizeof buf, "OPTION event-signal=%lx",
     400             :                 (unsigned long)get_agent_scd_notify_event ());
     401             : #else
     402           0 :       snprintf (buf, sizeof buf, "OPTION event-signal=%d", SIGUSR2);
     403             : #endif
     404           0 :       assuan_transact (ctx, buf, NULL, NULL, NULL, NULL, NULL, NULL);
     405             :     }
     406             : #endif /*HAVE_W32CE_SYSTEM*/
     407             : 
     408           0 :   primary_scd_ctx = ctx;
     409           0 :   primary_scd_ctx_reusable = 0;
     410             : 
     411             :  leave:
     412           5 :   xfree (abs_homedir);
     413           5 :   if (err)
     414             :     {
     415           5 :       unlock_scd (ctrl, err);
     416           5 :       if (ctx)
     417           5 :         assuan_release (ctx);
     418             :     }
     419             :   else
     420             :     {
     421           0 :       ctrl->scd_local->ctx = ctx;
     422             :     }
     423           5 :   rc = npth_mutex_unlock (&start_scd_lock);
     424           5 :   if (rc)
     425           0 :     log_error ("failed to release the start_scd lock: %s\n", strerror (rc));
     426           5 :   return err;
     427             : }
     428             : 
     429             : 
     430             : /* Check whether the SCdaemon is active.  This is a fast check without
     431             :    any locking and might give a wrong result if another thread is about
     432             :    to start the daemon or the daemon is about to be stopped.. */
     433             : int
     434           0 : agent_scd_check_running (void)
     435             : {
     436           0 :   return !!primary_scd_ctx;
     437             : }
     438             : 
     439             : 
     440             : /* Check whether the Scdaemon is still alive and clean it up if not. */
     441             : void
     442        1527 : agent_scd_check_aliveness (void)
     443             : {
     444             :   pid_t pid;
     445             : #ifdef HAVE_W32_SYSTEM
     446             :   DWORD rc;
     447             : #else
     448             :   int rc;
     449             : #endif
     450             :   struct timespec abstime;
     451             :   int err;
     452             : 
     453        1527 :   if (!primary_scd_ctx)
     454        3054 :     return; /* No scdaemon running. */
     455             : 
     456             :   /* This is not a critical function so we use a short timeout while
     457             :      acquiring the lock.  */
     458           0 :   npth_clock_gettime (&abstime);
     459           0 :   abstime.tv_sec += 1;
     460           0 :   err = npth_mutex_timedlock (&start_scd_lock, &abstime);
     461           0 :   if (err)
     462             :     {
     463           0 :       if (err == ETIMEDOUT)
     464             :         {
     465           0 :           if (opt.verbose > 1)
     466           0 :             log_info ("failed to acquire the start_scd lock while"
     467             :                       " doing an aliveness check: %s\n", strerror (err));
     468             :         }
     469             :       else
     470           0 :         log_error ("failed to acquire the start_scd lock while"
     471             :                    " doing an aliveness check: %s\n", strerror (err));
     472           0 :       return;
     473             :     }
     474             : 
     475           0 :   if (primary_scd_ctx)
     476             :     {
     477           0 :       pid = assuan_get_pid (primary_scd_ctx);
     478             : #ifdef HAVE_W32_SYSTEM
     479             :       /* If we have a PID we disconnect if either GetExitProcessCode
     480             :          fails or if ir returns the exit code of the scdaemon.  259 is
     481             :          the error code for STILL_ALIVE.  */
     482             :       if (pid != (pid_t)(void*)(-1) && pid
     483             :           && (!GetExitCodeProcess ((HANDLE)pid, &rc) || rc != 259))
     484             : #else
     485           0 :       if (pid != (pid_t)(-1) && pid
     486           0 :           && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
     487             : #endif
     488             :         {
     489             :           /* Okay, scdaemon died.  Disconnect the primary connection
     490             :              now but take care that it won't do another wait. Also
     491             :              cleanup all other connections and release their
     492             :              resources.  The next use will start a new daemon then.
     493             :              Due to the use of the START_SCD_LOCAL we are sure that
     494             :              none of these context are actually in use. */
     495             :           struct scd_local_s *sl;
     496             : 
     497           0 :           assuan_set_flag (primary_scd_ctx, ASSUAN_NO_WAITPID, 1);
     498           0 :           assuan_release (primary_scd_ctx);
     499             : 
     500           0 :           for (sl=scd_local_list; sl; sl = sl->next_local)
     501             :             {
     502           0 :               if (sl->ctx)
     503             :                 {
     504           0 :                   if (sl->ctx != primary_scd_ctx)
     505           0 :                     assuan_release (sl->ctx);
     506           0 :                   sl->ctx = NULL;
     507             :                 }
     508             :             }
     509             : 
     510           0 :           primary_scd_ctx = NULL;
     511           0 :           primary_scd_ctx_reusable = 0;
     512             : 
     513           0 :           xfree (socket_name);
     514           0 :           socket_name = NULL;
     515             :         }
     516             :     }
     517             : 
     518           0 :   err = npth_mutex_unlock (&start_scd_lock);
     519           0 :   if (err)
     520           0 :     log_error ("failed to release the start_scd lock while"
     521             :                " doing the aliveness check: %s\n", strerror (err));
     522             : }
     523             : 
     524             : 
     525             : 
     526             : /* Reset the SCD if it has been used.  Actually it is not a reset but
     527             :    a cleanup of resources used by the current connection. */
     528             : int
     529         729 : agent_reset_scd (ctrl_t ctrl)
     530             : {
     531         729 :   if (ctrl->scd_local)
     532             :     {
     533           5 :       if (ctrl->scd_local->ctx)
     534             :         {
     535             :           /* We can't disconnect the primary context because libassuan
     536             :              does a waitpid on it and thus the system would hang.
     537             :              Instead we send a reset and keep that connection for
     538             :              reuse. */
     539           0 :           if (ctrl->scd_local->ctx == primary_scd_ctx)
     540             :             {
     541             :               /* Send a RESTART to the SCD.  This is required for the
     542             :                  primary connection as a kind of virtual EOF; we don't
     543             :                  have another way to tell it that the next command
     544             :                  should be viewed as if a new connection has been
     545             :                  made.  For the non-primary connections this is not
     546             :                  needed as we simply close the socket.  We don't check
     547             :                  for an error here because the RESTART may fail for
     548             :                  example if the scdaemon has already been terminated.
     549             :                  Anyway, we need to set the reusable flag to make sure
     550             :                  that the aliveness check can clean it up. */
     551           0 :               assuan_transact (primary_scd_ctx, "RESTART",
     552             :                                NULL, NULL, NULL, NULL, NULL, NULL);
     553           0 :               primary_scd_ctx_reusable = 1;
     554             :             }
     555             :           else
     556           0 :             assuan_release (ctrl->scd_local->ctx);
     557           0 :           ctrl->scd_local->ctx = NULL;
     558             :         }
     559             : 
     560             :       /* Remove the local context from our list and release it. */
     561           5 :       if (!scd_local_list)
     562           0 :         BUG ();
     563           5 :       else if (scd_local_list == ctrl->scd_local)
     564           5 :         scd_local_list = ctrl->scd_local->next_local;
     565             :       else
     566             :         {
     567             :           struct scd_local_s *sl;
     568             : 
     569           0 :           for (sl=scd_local_list; sl->next_local; sl = sl->next_local)
     570           0 :             if (sl->next_local == ctrl->scd_local)
     571           0 :               break;
     572           0 :           if (!sl->next_local)
     573           0 :             BUG ();
     574           0 :           sl->next_local = ctrl->scd_local->next_local;
     575             :         }
     576           5 :       xfree (ctrl->scd_local);
     577           5 :       ctrl->scd_local = NULL;
     578             :     }
     579             : 
     580         729 :   return 0;
     581             : }
     582             : 
     583             : 
     584             : 
     585             : static gpg_error_t
     586           0 : learn_status_cb (void *opaque, const char *line)
     587             : {
     588           0 :   struct learn_parm_s *parm = opaque;
     589           0 :   const char *keyword = line;
     590             :   int keywordlen;
     591             : 
     592           0 :   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
     593             :     ;
     594           0 :   while (spacep (line))
     595           0 :     line++;
     596           0 :   if (keywordlen == 8 && !memcmp (keyword, "CERTINFO", keywordlen))
     597             :     {
     598           0 :       parm->certinfo_cb (parm->certinfo_cb_arg, line);
     599             :     }
     600           0 :   else if (keywordlen == 11 && !memcmp (keyword, "KEYPAIRINFO", keywordlen))
     601             :     {
     602           0 :       parm->kpinfo_cb (parm->kpinfo_cb_arg, line);
     603             :     }
     604           0 :   else if (keywordlen && *line)
     605             :     {
     606           0 :       parm->sinfo_cb (parm->sinfo_cb_arg, keyword, keywordlen, line);
     607             :     }
     608             : 
     609           0 :   return 0;
     610             : }
     611             : 
     612             : /* Perform the LEARN command and return a list of all private keys
     613             :    stored on the card. */
     614             : int
     615           0 : agent_card_learn (ctrl_t ctrl,
     616             :                   void (*kpinfo_cb)(void*, const char *),
     617             :                   void *kpinfo_cb_arg,
     618             :                   void (*certinfo_cb)(void*, const char *),
     619             :                   void *certinfo_cb_arg,
     620             :                   void (*sinfo_cb)(void*, const char *, size_t, const char *),
     621             :                   void *sinfo_cb_arg)
     622             : {
     623             :   int rc;
     624             :   struct learn_parm_s parm;
     625             : 
     626           0 :   rc = start_scd (ctrl);
     627           0 :   if (rc)
     628           0 :     return rc;
     629             : 
     630           0 :   memset (&parm, 0, sizeof parm);
     631           0 :   parm.kpinfo_cb = kpinfo_cb;
     632           0 :   parm.kpinfo_cb_arg = kpinfo_cb_arg;
     633           0 :   parm.certinfo_cb = certinfo_cb;
     634           0 :   parm.certinfo_cb_arg = certinfo_cb_arg;
     635           0 :   parm.sinfo_cb = sinfo_cb;
     636           0 :   parm.sinfo_cb_arg = sinfo_cb_arg;
     637           0 :   rc = assuan_transact (ctrl->scd_local->ctx, "LEARN --force",
     638             :                         NULL, NULL, NULL, NULL,
     639             :                         learn_status_cb, &parm);
     640           0 :   if (rc)
     641           0 :     return unlock_scd (ctrl, rc);
     642             : 
     643           0 :   return unlock_scd (ctrl, 0);
     644             : }
     645             : 
     646             : 
     647             : 
     648             : static gpg_error_t
     649           0 : get_serialno_cb (void *opaque, const char *line)
     650             : {
     651           0 :   char **serialno = opaque;
     652           0 :   const char *keyword = line;
     653             :   const char *s;
     654             :   int keywordlen, n;
     655             : 
     656           0 :   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
     657             :     ;
     658           0 :   while (spacep (line))
     659           0 :     line++;
     660             : 
     661           0 :   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
     662             :     {
     663           0 :       if (*serialno)
     664           0 :         return gpg_error (GPG_ERR_CONFLICT); /* Unexpected status line. */
     665           0 :       for (n=0,s=line; hexdigitp (s); s++, n++)
     666             :         ;
     667           0 :       if (!n || (n&1)|| !(spacep (s) || !*s) )
     668           0 :         return gpg_error (GPG_ERR_ASS_PARAMETER);
     669           0 :       *serialno = xtrymalloc (n+1);
     670           0 :       if (!*serialno)
     671           0 :         return out_of_core ();
     672           0 :       memcpy (*serialno, line, n);
     673           0 :       (*serialno)[n] = 0;
     674             :     }
     675             : 
     676           0 :   return 0;
     677             : }
     678             : 
     679             : /* Return the serial number of the card or an appropriate error.  The
     680             :    serial number is returned as a hexstring. */
     681             : int
     682           0 : agent_card_serialno (ctrl_t ctrl, char **r_serialno)
     683             : {
     684             :   int rc;
     685           0 :   char *serialno = NULL;
     686             : 
     687           0 :   rc = start_scd (ctrl);
     688           0 :   if (rc)
     689           0 :     return rc;
     690             : 
     691           0 :   rc = assuan_transact (ctrl->scd_local->ctx, "SERIALNO",
     692             :                         NULL, NULL, NULL, NULL,
     693             :                         get_serialno_cb, &serialno);
     694           0 :   if (rc)
     695             :     {
     696           0 :       xfree (serialno);
     697           0 :       return unlock_scd (ctrl, rc);
     698             :     }
     699           0 :   *r_serialno = serialno;
     700           0 :   return unlock_scd (ctrl, 0);
     701             : }
     702             : 
     703             : 
     704             : 
     705             : 
     706             : /* Handle the NEEDPIN inquiry. */
     707             : static gpg_error_t
     708           0 : inq_needpin (void *opaque, const char *line)
     709             : {
     710           0 :   struct inq_needpin_s *parm = opaque;
     711             :   const char *s;
     712             :   char *pin;
     713             :   size_t pinlen;
     714             :   int rc;
     715             : 
     716           0 :   parm->any_inq_seen = 1;
     717           0 :   if ((s = has_leading_keyword (line, "NEEDPIN")))
     718             :     {
     719           0 :       line = s;
     720           0 :       pinlen = 90;
     721           0 :       pin = gcry_malloc_secure (pinlen);
     722           0 :       if (!pin)
     723           0 :         return out_of_core ();
     724             : 
     725           0 :       rc = parm->getpin_cb (parm->getpin_cb_arg, line, pin, pinlen);
     726           0 :       if (!rc)
     727           0 :         rc = assuan_send_data (parm->ctx, pin, pinlen);
     728           0 :       xfree (pin);
     729             :     }
     730           0 :   else if ((s = has_leading_keyword (line, "POPUPPINPADPROMPT")))
     731             :     {
     732           0 :       rc = parm->getpin_cb (parm->getpin_cb_arg, s, NULL, 1);
     733             :     }
     734           0 :   else if ((s = has_leading_keyword (line, "DISMISSPINPADPROMPT")))
     735             :     {
     736           0 :       rc = parm->getpin_cb (parm->getpin_cb_arg, "", NULL, 0);
     737             :     }
     738           0 :   else if (parm->passthru)
     739             :     {
     740             :       unsigned char *value;
     741             :       size_t valuelen;
     742             :       int rest;
     743           0 :       int needrest = !strncmp (line, "KEYDATA", 8);
     744             : 
     745             :       /* Pass the inquiry up to our caller.  We limit the maximum
     746             :          amount to an arbitrary value.  As we know that the KEYDATA
     747             :          enquiry is pretty sensitive we disable logging then */
     748           0 :       if ((rest = (needrest
     749           0 :                    && !assuan_get_flag (parm->passthru, ASSUAN_CONFIDENTIAL))))
     750           0 :         assuan_begin_confidential (parm->passthru);
     751           0 :       rc = assuan_inquire (parm->passthru, line, &value, &valuelen, 8096);
     752           0 :       if (rest)
     753           0 :         assuan_end_confidential (parm->passthru);
     754           0 :       if (!rc)
     755             :         {
     756           0 :           if ((rest = (needrest
     757           0 :                        && !assuan_get_flag (parm->ctx, ASSUAN_CONFIDENTIAL))))
     758           0 :             assuan_begin_confidential (parm->ctx);
     759           0 :           rc = assuan_send_data (parm->ctx, value, valuelen);
     760           0 :           if (rest)
     761           0 :             assuan_end_confidential (parm->ctx);
     762           0 :           xfree (value);
     763             :         }
     764             :       else
     765           0 :         log_error ("error forwarding inquiry '%s': %s\n",
     766             :                    line, gpg_strerror (rc));
     767             :     }
     768             :   else
     769             :     {
     770           0 :       log_error ("unsupported inquiry '%s'\n", line);
     771           0 :       rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
     772             :     }
     773             : 
     774           0 :   return rc;
     775             : }
     776             : 
     777             : 
     778             : /* Helper returning a command option to describe the used hash
     779             :    algorithm.  See scd/command.c:cmd_pksign.  */
     780             : static const char *
     781           0 : hash_algo_option (int algo)
     782             : {
     783           0 :   switch (algo)
     784             :     {
     785           0 :     case GCRY_MD_MD5   : return "--hash=md5";
     786           0 :     case GCRY_MD_RMD160: return "--hash=rmd160";
     787           0 :     case GCRY_MD_SHA1  : return "--hash=sha1";
     788           0 :     case GCRY_MD_SHA224: return "--hash=sha224";
     789           0 :     case GCRY_MD_SHA256: return "--hash=sha256";
     790           0 :     case GCRY_MD_SHA384: return "--hash=sha384";
     791           0 :     case GCRY_MD_SHA512: return "--hash=sha512";
     792           0 :     default:             return "";
     793             :     }
     794             : }
     795             : 
     796             : 
     797             : static gpg_error_t
     798           0 : cancel_inquire (ctrl_t ctrl, gpg_error_t rc)
     799             : {
     800           0 :   gpg_error_t oldrc = rc;
     801             : 
     802             :   /* The inquire callback was called and transact returned a
     803             :      cancel error.  We assume that the inquired process sent a
     804             :      CANCEL.  The passthrough code is not able to pass on the
     805             :      CANCEL and thus scdaemon would stuck on this.  As a
     806             :      workaround we send a CANCEL now.  */
     807           0 :   rc = assuan_write_line (ctrl->scd_local->ctx, "CAN");
     808           0 :   if (!rc) {
     809             :     char *line;
     810             :     size_t len;
     811             : 
     812           0 :     rc = assuan_read_line (ctrl->scd_local->ctx, &line, &len);
     813           0 :     if (!rc)
     814           0 :       rc = oldrc;
     815             :   }
     816             : 
     817           0 :   return rc;
     818             : }
     819             : 
     820             : /* Create a signature using the current card.  MDALGO is either 0 or
     821             :    gives the digest algorithm.  */
     822             : int
     823           0 : agent_card_pksign (ctrl_t ctrl,
     824             :                    const char *keyid,
     825             :                    int (*getpin_cb)(void *, const char *, char*, size_t),
     826             :                    void *getpin_cb_arg,
     827             :                    int mdalgo,
     828             :                    const unsigned char *indata, size_t indatalen,
     829             :                    unsigned char **r_buf, size_t *r_buflen)
     830             : {
     831             :   int rc;
     832             :   char line[ASSUAN_LINELENGTH];
     833             :   membuf_t data;
     834             :   struct inq_needpin_s inqparm;
     835             : 
     836           0 :   *r_buf = NULL;
     837           0 :   rc = start_scd (ctrl);
     838           0 :   if (rc)
     839           0 :     return rc;
     840             : 
     841           0 :   if (indatalen*2 + 50 > DIM(line))
     842           0 :     return unlock_scd (ctrl, gpg_error (GPG_ERR_GENERAL));
     843             : 
     844           0 :   bin2hex (indata, indatalen, stpcpy (line, "SETDATA "));
     845             : 
     846           0 :   rc = assuan_transact (ctrl->scd_local->ctx, line,
     847             :                         NULL, NULL, NULL, NULL, NULL, NULL);
     848           0 :   if (rc)
     849           0 :     return unlock_scd (ctrl, rc);
     850             : 
     851           0 :   init_membuf (&data, 1024);
     852           0 :   inqparm.ctx = ctrl->scd_local->ctx;
     853           0 :   inqparm.getpin_cb = getpin_cb;
     854           0 :   inqparm.getpin_cb_arg = getpin_cb_arg;
     855           0 :   inqparm.passthru = 0;
     856           0 :   inqparm.any_inq_seen = 0;
     857           0 :   if (ctrl->use_auth_call)
     858           0 :     snprintf (line, sizeof line, "PKAUTH %s", keyid);
     859             :   else
     860           0 :     snprintf (line, sizeof line, "PKSIGN %s %s",
     861             :               hash_algo_option (mdalgo), keyid);
     862           0 :   rc = assuan_transact (ctrl->scd_local->ctx, line,
     863             :                         put_membuf_cb, &data,
     864             :                         inq_needpin, &inqparm,
     865             :                         NULL, NULL);
     866           0 :   if (inqparm.any_inq_seen && (gpg_err_code(rc) == GPG_ERR_CANCELED ||
     867           0 :         gpg_err_code(rc) == GPG_ERR_ASS_CANCELED))
     868           0 :     rc = cancel_inquire (ctrl, rc);
     869             : 
     870           0 :   if (rc)
     871             :     {
     872             :       size_t len;
     873             : 
     874           0 :       xfree (get_membuf (&data, &len));
     875           0 :       return unlock_scd (ctrl, rc);
     876             :     }
     877             : 
     878           0 :   *r_buf = get_membuf (&data, r_buflen);
     879           0 :   return unlock_scd (ctrl, 0);
     880             : }
     881             : 
     882             : 
     883             : 
     884             : 
     885             : /* Check whether there is any padding info from scdaemon.  */
     886             : static gpg_error_t
     887           0 : padding_info_cb (void *opaque, const char *line)
     888             : {
     889           0 :   int *r_padding = opaque;
     890             :   const char *s;
     891             : 
     892           0 :   if ((s=has_leading_keyword (line, "PADDING")))
     893             :     {
     894           0 :       *r_padding = atoi (s);
     895             :     }
     896             : 
     897           0 :   return 0;
     898             : }
     899             : 
     900             : 
     901             : /* Decipher INDATA using the current card.  Note that the returned
     902             :    value is not an s-expression but the raw data as returned by
     903             :    scdaemon.  The padding information is stored at R_PADDING with -1
     904             :    for not known.  */
     905             : int
     906           0 : agent_card_pkdecrypt (ctrl_t ctrl,
     907             :                       const char *keyid,
     908             :                       int (*getpin_cb)(void *, const char *, char*, size_t),
     909             :                       void *getpin_cb_arg,
     910             :                       const unsigned char *indata, size_t indatalen,
     911             :                       char **r_buf, size_t *r_buflen, int *r_padding)
     912             : {
     913             :   int rc, i;
     914             :   char *p, line[ASSUAN_LINELENGTH];
     915             :   membuf_t data;
     916             :   struct inq_needpin_s inqparm;
     917             :   size_t len;
     918             : 
     919           0 :   *r_buf = NULL;
     920           0 :   *r_padding = -1; /* Unknown.  */
     921           0 :   rc = start_scd (ctrl);
     922           0 :   if (rc)
     923           0 :     return rc;
     924             : 
     925             :   /* FIXME: use secure memory where appropriate */
     926             : 
     927           0 :   for (len = 0; len < indatalen;)
     928             :     {
     929           0 :       p = stpcpy (line, "SETDATA ");
     930           0 :       if (len)
     931           0 :         p = stpcpy (p, "--append ");
     932           0 :       for (i=0; len < indatalen && (i*2 < DIM(line)-50); i++, len++)
     933             :         {
     934           0 :           sprintf (p, "%02X", indata[len]);
     935           0 :           p += 2;
     936             :         }
     937           0 :       rc = assuan_transact (ctrl->scd_local->ctx, line,
     938             :                             NULL, NULL, NULL, NULL, NULL, NULL);
     939           0 :       if (rc)
     940           0 :         return unlock_scd (ctrl, rc);
     941             :     }
     942             : 
     943           0 :   init_membuf (&data, 1024);
     944           0 :   inqparm.ctx = ctrl->scd_local->ctx;
     945           0 :   inqparm.getpin_cb = getpin_cb;
     946           0 :   inqparm.getpin_cb_arg = getpin_cb_arg;
     947           0 :   inqparm.passthru = 0;
     948           0 :   inqparm.any_inq_seen = 0;
     949           0 :   snprintf (line, DIM(line)-1, "PKDECRYPT %s", keyid);
     950           0 :   line[DIM(line)-1] = 0;
     951           0 :   rc = assuan_transact (ctrl->scd_local->ctx, line,
     952             :                         put_membuf_cb, &data,
     953             :                         inq_needpin, &inqparm,
     954             :                         padding_info_cb, r_padding);
     955           0 :   if (inqparm.any_inq_seen && (gpg_err_code(rc) == GPG_ERR_CANCELED ||
     956           0 :         gpg_err_code(rc) == GPG_ERR_ASS_CANCELED))
     957           0 :     rc = cancel_inquire (ctrl, rc);
     958             : 
     959           0 :   if (rc)
     960             :     {
     961           0 :       xfree (get_membuf (&data, &len));
     962           0 :       return unlock_scd (ctrl, rc);
     963             :     }
     964           0 :   *r_buf = get_membuf (&data, r_buflen);
     965           0 :   if (!*r_buf)
     966           0 :     return unlock_scd (ctrl, gpg_error (GPG_ERR_ENOMEM));
     967             : 
     968           0 :   return unlock_scd (ctrl, 0);
     969             : }
     970             : 
     971             : 
     972             : 
     973             : /* Read a certificate with ID into R_BUF and R_BUFLEN. */
     974             : int
     975           0 : agent_card_readcert (ctrl_t ctrl,
     976             :                      const char *id, char **r_buf, size_t *r_buflen)
     977             : {
     978             :   int rc;
     979             :   char line[ASSUAN_LINELENGTH];
     980             :   membuf_t data;
     981             :   size_t len;
     982             : 
     983           0 :   *r_buf = NULL;
     984           0 :   rc = start_scd (ctrl);
     985           0 :   if (rc)
     986           0 :     return rc;
     987             : 
     988           0 :   init_membuf (&data, 1024);
     989           0 :   snprintf (line, DIM(line)-1, "READCERT %s", id);
     990           0 :   line[DIM(line)-1] = 0;
     991           0 :   rc = assuan_transact (ctrl->scd_local->ctx, line,
     992             :                         put_membuf_cb, &data,
     993             :                         NULL, NULL,
     994             :                         NULL, NULL);
     995           0 :   if (rc)
     996             :     {
     997           0 :       xfree (get_membuf (&data, &len));
     998           0 :       return unlock_scd (ctrl, rc);
     999             :     }
    1000           0 :   *r_buf = get_membuf (&data, r_buflen);
    1001           0 :   if (!*r_buf)
    1002           0 :     return unlock_scd (ctrl, gpg_error (GPG_ERR_ENOMEM));
    1003             : 
    1004           0 :   return unlock_scd (ctrl, 0);
    1005             : }
    1006             : 
    1007             : 
    1008             : 
    1009             : /* Read a key with ID and return it in an allocate buffer pointed to
    1010             :    by r_BUF as a valid S-expression. */
    1011             : int
    1012           0 : agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf)
    1013             : {
    1014             :   int rc;
    1015             :   char line[ASSUAN_LINELENGTH];
    1016             :   membuf_t data;
    1017             :   size_t len, buflen;
    1018             : 
    1019           0 :   *r_buf = NULL;
    1020           0 :   rc = start_scd (ctrl);
    1021           0 :   if (rc)
    1022           0 :     return rc;
    1023             : 
    1024           0 :   init_membuf (&data, 1024);
    1025           0 :   snprintf (line, DIM(line)-1, "READKEY %s", id);
    1026           0 :   line[DIM(line)-1] = 0;
    1027           0 :   rc = assuan_transact (ctrl->scd_local->ctx, line,
    1028             :                         put_membuf_cb, &data,
    1029             :                         NULL, NULL,
    1030             :                         NULL, NULL);
    1031           0 :   if (rc)
    1032             :     {
    1033           0 :       xfree (get_membuf (&data, &len));
    1034           0 :       return unlock_scd (ctrl, rc);
    1035             :     }
    1036           0 :   *r_buf = get_membuf (&data, &buflen);
    1037           0 :   if (!*r_buf)
    1038           0 :     return unlock_scd (ctrl, gpg_error (GPG_ERR_ENOMEM));
    1039             : 
    1040           0 :   if (!gcry_sexp_canon_len (*r_buf, buflen, NULL, NULL))
    1041             :     {
    1042           0 :       xfree (*r_buf); *r_buf = NULL;
    1043           0 :       return unlock_scd (ctrl, gpg_error (GPG_ERR_INV_VALUE));
    1044             :     }
    1045             : 
    1046           0 :   return unlock_scd (ctrl, 0);
    1047             : }
    1048             : 
    1049             : 
    1050             : struct writekey_parm_s
    1051             : {
    1052             :   assuan_context_t ctx;
    1053             :   int (*getpin_cb)(void *, const char *, char*, size_t);
    1054             :   void *getpin_cb_arg;
    1055             :   assuan_context_t passthru;
    1056             :   int any_inq_seen;
    1057             :   /**/
    1058             :   const unsigned char *keydata;
    1059             :   size_t keydatalen;
    1060             : };
    1061             : 
    1062             : /* Handle a KEYDATA inquiry.  Note, we only send the data,
    1063             :    assuan_transact takes care of flushing and writing the end */
    1064             : static gpg_error_t
    1065           0 : inq_writekey_parms (void *opaque, const char *line)
    1066             : {
    1067           0 :   struct writekey_parm_s *parm = opaque;
    1068             : 
    1069           0 :   if (has_leading_keyword (line, "KEYDATA"))
    1070           0 :     return assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
    1071             :   else
    1072           0 :     return inq_needpin (opaque, line);
    1073             : }
    1074             : 
    1075             : 
    1076             : int
    1077           0 : agent_card_writekey (ctrl_t ctrl,  int force, const char *serialno,
    1078             :                      const char *id, const char *keydata, size_t keydatalen,
    1079             :                      int (*getpin_cb)(void *, const char *, char*, size_t),
    1080             :                      void *getpin_cb_arg)
    1081             : {
    1082             :   int rc;
    1083             :   char line[ASSUAN_LINELENGTH];
    1084             :   struct writekey_parm_s parms;
    1085             : 
    1086             :   (void)serialno;
    1087           0 :   rc = start_scd (ctrl);
    1088           0 :   if (rc)
    1089           0 :     return rc;
    1090             : 
    1091           0 :   snprintf (line, DIM(line)-1, "WRITEKEY %s%s", force ? "--force " : "", id);
    1092           0 :   line[DIM(line)-1] = 0;
    1093           0 :   parms.ctx = ctrl->scd_local->ctx;
    1094           0 :   parms.getpin_cb = getpin_cb;
    1095           0 :   parms.getpin_cb_arg = getpin_cb_arg;
    1096           0 :   parms.passthru = 0;
    1097           0 :   parms.any_inq_seen = 0;
    1098           0 :   parms.keydata = keydata;
    1099           0 :   parms.keydatalen = keydatalen;
    1100             : 
    1101           0 :   rc = assuan_transact (ctrl->scd_local->ctx, line, NULL, NULL,
    1102             :                         inq_writekey_parms, &parms, NULL, NULL);
    1103           0 :   if (parms.any_inq_seen && (gpg_err_code(rc) == GPG_ERR_CANCELED ||
    1104           0 :                              gpg_err_code(rc) == GPG_ERR_ASS_CANCELED))
    1105           0 :     rc = cancel_inquire (ctrl, rc);
    1106           0 :   return unlock_scd (ctrl, rc);
    1107             : }
    1108             : 
    1109             : /* Type used with the card_getattr_cb.  */
    1110             : struct card_getattr_parm_s {
    1111             :   const char *keyword;  /* Keyword to look for.  */
    1112             :   size_t keywordlen;    /* strlen of KEYWORD.  */
    1113             :   char *data;           /* Malloced and unescaped data.  */
    1114             :   int error;            /* ERRNO value or 0 on success. */
    1115             : };
    1116             : 
    1117             : /* Callback function for agent_card_getattr.  */
    1118             : static gpg_error_t
    1119           0 : card_getattr_cb (void *opaque, const char *line)
    1120             : {
    1121           0 :   struct card_getattr_parm_s *parm = opaque;
    1122           0 :   const char *keyword = line;
    1123             :   int keywordlen;
    1124             : 
    1125           0 :   if (parm->data)
    1126           0 :     return 0; /* We want only the first occurrence.  */
    1127             : 
    1128           0 :   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
    1129             :     ;
    1130           0 :   while (spacep (line))
    1131           0 :     line++;
    1132             : 
    1133           0 :   if (keywordlen == parm->keywordlen
    1134           0 :       && !memcmp (keyword, parm->keyword, keywordlen))
    1135             :     {
    1136           0 :       parm->data = percent_plus_unescape ((const unsigned char*)line, 0xff);
    1137           0 :       if (!parm->data)
    1138           0 :         parm->error = errno;
    1139             :     }
    1140             : 
    1141           0 :   return 0;
    1142             : }
    1143             : 
    1144             : 
    1145             : /* Call the agent to retrieve a single line data object. On success
    1146             :    the object is malloced and stored at RESULT; it is guaranteed that
    1147             :    NULL is never stored in this case.  On error an error code is
    1148             :    returned and NULL stored at RESULT. */
    1149             : gpg_error_t
    1150           5 : agent_card_getattr (ctrl_t ctrl, const char *name, char **result)
    1151             : {
    1152             :   int err;
    1153             :   struct card_getattr_parm_s parm;
    1154             :   char line[ASSUAN_LINELENGTH];
    1155             : 
    1156           5 :   *result = NULL;
    1157             : 
    1158           5 :   if (!*name)
    1159           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    1160             : 
    1161           5 :   memset (&parm, 0, sizeof parm);
    1162           5 :   parm.keyword = name;
    1163           5 :   parm.keywordlen = strlen (name);
    1164             : 
    1165             :   /* We assume that NAME does not need escaping. */
    1166           5 :   if (8 + strlen (name) > DIM(line)-1)
    1167           0 :     return gpg_error (GPG_ERR_TOO_LARGE);
    1168           5 :   stpcpy (stpcpy (line, "GETATTR "), name);
    1169             : 
    1170           5 :   err = start_scd (ctrl);
    1171           5 :   if (err)
    1172           5 :     return err;
    1173             : 
    1174           0 :   err = assuan_transact (ctrl->scd_local->ctx, line,
    1175             :                          NULL, NULL, NULL, NULL,
    1176             :                          card_getattr_cb, &parm);
    1177           0 :   if (!err && parm.error)
    1178           0 :     err = gpg_error_from_errno (parm.error);
    1179             : 
    1180           0 :   if (!err && !parm.data)
    1181           0 :     err = gpg_error (GPG_ERR_NO_DATA);
    1182             : 
    1183           0 :   if (!err)
    1184           0 :     *result = parm.data;
    1185             :   else
    1186           0 :     xfree (parm.data);
    1187             : 
    1188           0 :   return unlock_scd (ctrl, err);
    1189             : }
    1190             : 
    1191             : 
    1192             : 
    1193             : 
    1194             : static gpg_error_t
    1195           0 : pass_status_thru (void *opaque, const char *line)
    1196             : {
    1197           0 :   assuan_context_t ctx = opaque;
    1198             :   char keyword[200];
    1199             :   int i;
    1200             : 
    1201           0 :   if (line[0] == '#' && (!line[1] || spacep (line+1)))
    1202             :     {
    1203             :       /* We are called in convey comments mode.  Now, if we see a
    1204             :          comment marker as keyword we forward the line verbatim to the
    1205             :          the caller.  This way the comment lines from scdaemon won't
    1206             :          appear as status lines with keyword '#'.  */
    1207           0 :       assuan_write_line (ctx, line);
    1208             :     }
    1209             :   else
    1210             :     {
    1211           0 :       for (i=0; *line && !spacep (line) && i < DIM(keyword)-1; line++, i++)
    1212           0 :         keyword[i] = *line;
    1213           0 :       keyword[i] = 0;
    1214             : 
    1215             :       /* Truncate any remaining keyword stuff.  */
    1216           0 :       for (; *line && !spacep (line); line++)
    1217             :         ;
    1218           0 :       while (spacep (line))
    1219           0 :         line++;
    1220             : 
    1221           0 :       assuan_write_status (ctx, keyword, line);
    1222             :     }
    1223           0 :   return 0;
    1224             : }
    1225             : 
    1226             : static gpg_error_t
    1227           0 : pass_data_thru (void *opaque, const void *buffer, size_t length)
    1228             : {
    1229           0 :   assuan_context_t ctx = opaque;
    1230             : 
    1231           0 :   assuan_send_data (ctx, buffer, length);
    1232           0 :   return 0;
    1233             : }
    1234             : 
    1235             : 
    1236             : /* Send the line CMDLINE with command for the SCDdaemon to it and send
    1237             :    all status messages back.  This command is used as a general quoting
    1238             :    mechanism to pass everything verbatim to SCDAEMON.  The PIN
    1239             :    inquiry is handled inside gpg-agent.  */
    1240             : int
    1241           0 : agent_card_scd (ctrl_t ctrl, const char *cmdline,
    1242             :                 int (*getpin_cb)(void *, const char *, char*, size_t),
    1243             :                 void *getpin_cb_arg, void *assuan_context)
    1244             : {
    1245             :   int rc;
    1246             :   struct inq_needpin_s inqparm;
    1247             :   int saveflag;
    1248             : 
    1249           0 :   rc = start_scd (ctrl);
    1250           0 :   if (rc)
    1251           0 :     return rc;
    1252             : 
    1253           0 :   inqparm.ctx = ctrl->scd_local->ctx;
    1254           0 :   inqparm.getpin_cb = getpin_cb;
    1255           0 :   inqparm.getpin_cb_arg = getpin_cb_arg;
    1256           0 :   inqparm.passthru = assuan_context;
    1257           0 :   inqparm.any_inq_seen = 0;
    1258           0 :   saveflag = assuan_get_flag (ctrl->scd_local->ctx, ASSUAN_CONVEY_COMMENTS);
    1259           0 :   assuan_set_flag (ctrl->scd_local->ctx, ASSUAN_CONVEY_COMMENTS, 1);
    1260           0 :   rc = assuan_transact (ctrl->scd_local->ctx, cmdline,
    1261             :                         pass_data_thru, assuan_context,
    1262             :                         inq_needpin, &inqparm,
    1263             :                         pass_status_thru, assuan_context);
    1264           0 :   if (inqparm.any_inq_seen && gpg_err_code(rc) == GPG_ERR_ASS_CANCELED)
    1265           0 :     rc = cancel_inquire (ctrl, rc);
    1266             : 
    1267           0 :   assuan_set_flag (ctrl->scd_local->ctx, ASSUAN_CONVEY_COMMENTS, saveflag);
    1268           0 :   if (rc)
    1269             :     {
    1270           0 :       return unlock_scd (ctrl, rc);
    1271             :     }
    1272             : 
    1273           0 :   return unlock_scd (ctrl, 0);
    1274             : }

Generated by: LCOV version 1.11