LCOV - code coverage report
Current view: top level - agent - call-scd.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 12 495 2.4 %
Date: 2015-11-05 17:10:59 Functions: 3 28 10.7 %

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

Generated by: LCOV version 1.11