~ubuntu-branches/ubuntu/oneiric/gnupg2/oneiric-updates

« back to all changes in this revision

Viewing changes to agent/call-scd.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-10-04 10:25:53 UTC
  • mfrom: (5.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081004102553-fv62pp8dsitxli47
Tags: 2.0.9-3.1
* Non-maintainer upload.
* agent/gpg-agent.c: Deinit the threading library before exec'ing
  the command to run in --daemon mode. And because that still doesn't
  restore the sigprocmask, do that manually. Closes: #499569

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* call-scd.c - fork of the scdaemon to do SC operations
2
 
 *      Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
 
2
 *      Copyright (C) 2001, 2002, 2005, 2007 Free Software Foundation, Inc.
3
3
 *
4
4
 * This file is part of GnuPG.
5
5
 *
6
6
 * GnuPG is free software; you can redistribute it and/or modify
7
7
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * the Free Software Foundation; either version 3 of the License, or
9
9
 * (at your option) any later version.
10
10
 *
11
11
 * GnuPG is distributed in the hope that it will be useful,
14
14
 * GNU General Public License for more details.
15
15
 *
16
16
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
17
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19
18
 */
20
19
 
21
20
#include <config.h>
26
25
#include <ctype.h>
27
26
#include <assert.h>
28
27
#include <unistd.h>
 
28
#include <signal.h>
29
29
#include <sys/stat.h>
30
30
#include <sys/types.h>
31
31
#ifndef HAVE_W32_SYSTEM
45
45
/* Definition of module local data of the CTRL structure.  */
46
46
struct scd_local_s
47
47
{
 
48
  /* We keep a list of all allocated context with a an achnor at
 
49
     SCD_LOCAL_LIST (see below). */
 
50
  struct scd_local_s *next_local;
 
51
 
 
52
  /* We need to get back to the ctrl object actually referencing this
 
53
     structure.  This is really an awkward way of enumerint the lcoal
 
54
     contects.  A much cleaner way would be to keep a global list of
 
55
     ctrl objects to enumerate them.  */
 
56
  ctrl_t ctrl_backlink;
 
57
 
48
58
  assuan_context_t ctx; /* NULL or session context for the SCdaemon
49
59
                           used with this connection. */
50
60
  int locked;           /* This flag is used to assert proper use of
69
79
  assuan_context_t ctx;
70
80
  int (*getpin_cb)(void *, const char *, char*, size_t);
71
81
  void *getpin_cb_arg;
 
82
  assuan_context_t passthru;  /* If not NULL, pass unknown inquiries
 
83
                                 up to the caller.  */
72
84
};
73
85
 
74
86
 
 
87
/* To keep track of all active SCD contexts, we keep a linked list
 
88
   anchored at this variable. */
 
89
static struct scd_local_s *scd_local_list;
 
90
 
75
91
/* A Mutex used inside the start_scd function. */
76
92
static pth_mutex_t start_scd_lock;
77
93
 
119
135
static void
120
136
dump_mutex_state (pth_mutex_t *m)
121
137
{
 
138
#ifdef _W32_PTH_H
 
139
  log_printf ("unknown under W32");
 
140
#else
122
141
  if (!(m->mx_state & PTH_MUTEX_INITIALIZED))
123
142
    log_printf ("not_initialized");
124
143
  else if (!(m->mx_state & PTH_MUTEX_LOCKED))
125
144
    log_printf ("not_locked");
126
145
  else
127
146
    log_printf ("locked tid=0x%lx count=%lu", (long)m->mx_owner, m->mx_count);
 
147
#endif
128
148
}
129
149
 
130
150
 
178
198
 
179
199
/* Fork off the SCdaemon if this has not already been done.  Lock the
180
200
   daemon and make sure that a proper context has been setup in CTRL.
181
 
   Thsi fucntion might also lock the daemon, which means that the
 
201
   This function might also lock the daemon, which means that the
182
202
   caller must call unlock_scd after this fucntion has returned
183
203
   success and the actual Assuan transaction been done. */
184
204
static int
201
221
    {
202
222
      ctrl->scd_local = xtrycalloc (1, sizeof *ctrl->scd_local);
203
223
      if (!ctrl->scd_local)
204
 
        return gpg_error_from_errno (errno);
 
224
        return gpg_error_from_syserror ();
 
225
      ctrl->scd_local->ctrl_backlink = ctrl;
 
226
      ctrl->scd_local->next_local = scd_local_list;
 
227
      scd_local_list = ctrl->scd_local;
205
228
    }
206
229
 
207
230
 
216
239
 
217
240
  if (ctrl->scd_local->ctx)
218
241
    return 0; /* Okay, the context is fine.  We used to test for an
219
 
                 alive context here and do an disconnect.  How that we
 
242
                 alive context here and do an disconnect.  Now that we
220
243
                 have a ticker function to check for it, it is easier
221
244
                 not to check here but to let the connection run on an
222
245
                 error instead. */
248
271
      if (rc)
249
272
        {
250
273
          log_error ("can't connect to socket `%s': %s\n",
251
 
                     socket_name, assuan_strerror (rc));
 
274
                     socket_name, gpg_strerror (rc));
252
275
          err = gpg_error (GPG_ERR_NO_SCDAEMON);
253
276
          goto leave;
254
277
        }
271
294
      
272
295
  if (fflush (NULL))
273
296
    {
274
 
      err = gpg_error (gpg_err_code_from_errno (errno));
 
297
#ifndef HAVE_W32_SYSTEM
 
298
      err = gpg_error_from_syserror ();
 
299
#endif
275
300
      log_error ("error flushing pending output: %s\n", strerror (errno));
 
301
      /* At least Windows XP fails here with EBADF.  According to docs
 
302
         and Wine an fflush(NULL) is the same as _flushall.  However
 
303
         the Wime implementaion does not flush stdin,stdout and stderr
 
304
         - see above.  Lets try to ignore the error. */
 
305
#ifndef HAVE_W32_SYSTEM
276
306
      goto leave;
 
307
#endif
277
308
    }
278
309
 
279
310
  if (!opt.scdaemon_program || !*opt.scdaemon_program)
280
 
    opt.scdaemon_program = GNUPG_DEFAULT_SCDAEMON;
 
311
    opt.scdaemon_program = gnupg_module_name (GNUPG_MODULE_NAME_SCDAEMON);
281
312
  if ( !(pgmname = strrchr (opt.scdaemon_program, '/')))
282
313
    pgmname = opt.scdaemon_program;
283
314
  else
296
327
    }
297
328
  no_close_list[i] = -1;
298
329
 
299
 
  /* Connect to the pinentry and perform initial handshaking */
300
 
  rc = assuan_pipe_connect2 (&ctx, opt.scdaemon_program, (char**)argv,
301
 
                             no_close_list, atfork_cb, NULL);
 
330
  /* Connect to the pinentry and perform initial handshaking.  Use
 
331
     detached flag (128) so that under W32 SCDAEMON does not show up a
 
332
     new window.  */
 
333
  rc = assuan_pipe_connect_ext (&ctx, opt.scdaemon_program, argv,
 
334
                                no_close_list, atfork_cb, NULL, 128);
302
335
  if (rc)
303
336
    {
304
337
      log_error ("can't connect to the SCdaemon: %s\n",
305
 
                 assuan_strerror (rc));
 
338
                 gpg_strerror (rc));
306
339
      err = gpg_error (GPG_ERR_NO_SCDAEMON);
307
340
      goto leave;
308
341
    }
341
374
  }
342
375
 
343
376
  /* Tell the scdaemon we want him to send us an event signal. */
344
 
#ifndef HAVE_W32_SYSTEM
345
377
  {
346
378
    char buf[100];
347
379
 
348
 
    sprintf (buf, "OPTION event-signal=%d", SIGUSR2);
 
380
#ifdef HAVE_W32_SYSTEM
 
381
    snprintf (buf, sizeof buf, "OPTION event-signal=%lx", 
 
382
              (unsigned long)get_agent_scd_notify_event ());
 
383
#else
 
384
    snprintf (buf, sizeof buf, "OPTION event-signal=%d", SIGUSR2);
 
385
#endif
349
386
    assuan_transact (ctx, buf, NULL, NULL, NULL, NULL, NULL, NULL);
350
387
  }
351
 
#endif
352
388
 
353
389
  primary_scd_ctx = ctx;
354
390
  primary_scd_ctx_reusable = 0;
375
411
  pth_event_t evt;
376
412
  pid_t pid;
377
413
  int rc;
 
414
#ifdef HAVE_W32_SYSTEM
 
415
  DWORD dummyec;
 
416
#endif
378
417
 
379
418
  if (!primary_scd_ctx)
380
419
    return; /* No scdaemon running. */
401
440
  if (primary_scd_ctx)
402
441
    {
403
442
      pid = assuan_get_pid (primary_scd_ctx);
 
443
#ifdef HAVE_W32_SYSTEM
 
444
      if (pid != (pid_t)(void*)(-1) && pid
 
445
          && !GetExitCodeProcess ((HANDLE)pid, &dummyec))
 
446
#else
404
447
      if (pid != (pid_t)(-1) && pid
405
448
          && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
 
449
#endif
406
450
        {
407
 
          /* Okay, scdaemon died.  Disconnect the primary connection now
408
 
             but take care that it won't do another wait. */
 
451
          /* Okay, scdaemon died.  Disconnect the primary connection
 
452
             now but take care that it won't do another wait. Also
 
453
             cleanup all other connections and release their
 
454
             resources.  The next use will start a new daemon then.
 
455
             Due to the use of the START_SCD_LOCAL we are sure that
 
456
             none of these context are actually in use. */
 
457
          struct scd_local_s *sl;
 
458
 
409
459
          assuan_set_flag (primary_scd_ctx, ASSUAN_NO_WAITPID, 1);
410
460
          assuan_disconnect (primary_scd_ctx);
 
461
 
 
462
          for (sl=scd_local_list; sl; sl = sl->next_local)
 
463
            {
 
464
              if (sl->ctx)
 
465
                {
 
466
                  if (sl->ctx != primary_scd_ctx)
 
467
                    assuan_disconnect (sl->ctx);
 
468
                  sl->ctx = NULL;
 
469
                }
 
470
            }
 
471
          
411
472
          primary_scd_ctx = NULL;
412
473
          primary_scd_ctx_reusable = 0;
 
474
 
413
475
          xfree (socket_name);
414
476
          socket_name = NULL;
415
477
        }
422
484
 
423
485
 
424
486
 
425
 
/* Reset the SCD if it has been used. */
 
487
/* Reset the SCD if it has been used.  Actually it is not a reset but
 
488
   a cleanup of resources used by the current connection. */
426
489
int
427
490
agent_reset_scd (ctrl_t ctrl)
428
491
{
436
499
             reuse. */
437
500
          if (ctrl->scd_local->ctx == primary_scd_ctx)
438
501
            {
439
 
              /* The RESET may fail for example if the scdaemon has
440
 
                 already been terminated.  We need to set the reusable
441
 
                 flag anyway to make sure that the aliveness check can
442
 
                 clean it up. */
443
 
              assuan_transact (primary_scd_ctx, "RESET",
 
502
              /* Send a RESTART to the SCD.  This is required for the
 
503
                 primary connection as a kind of virtual EOF; we don't
 
504
                 have another way to tell it that the next command
 
505
                 should be viewed as if a new connection has been
 
506
                 made.  For the non-primary connections this is not
 
507
                 needed as we simply close the socket.  We don't check
 
508
                 for an error here because the RESTART may fail for
 
509
                 example if the scdaemon has already been terminated.
 
510
                 Anyway, we need to set the reusable flag to make sure
 
511
                 that the aliveness check can clean it up. */
 
512
              assuan_transact (primary_scd_ctx, "RESTART",
444
513
                               NULL, NULL, NULL, NULL, NULL, NULL);
445
514
              primary_scd_ctx_reusable = 1;
446
515
            }
447
516
          else
448
517
            assuan_disconnect (ctrl->scd_local->ctx);
 
518
          ctrl->scd_local->ctx = NULL;
 
519
        }
 
520
      
 
521
      /* Remove the local context from our list and release it. */
 
522
      if (!scd_local_list)
 
523
        BUG ();
 
524
      else if (scd_local_list == ctrl->scd_local)
 
525
        scd_local_list = ctrl->scd_local->next_local;
 
526
      else
 
527
        {
 
528
          struct scd_local_s *sl;
 
529
      
 
530
          for (sl=scd_local_list; sl->next_local; sl = sl->next_local)
 
531
            if (sl->next_local == ctrl->scd_local)
 
532
              break;
 
533
          if (!sl->next_local)
 
534
            BUG ();
 
535
          sl->next_local = ctrl->scd_local->next_local;
449
536
        }
450
537
      xfree (ctrl->scd_local);
451
538
      ctrl->scd_local = NULL;
493
580
 
494
581
 
495
582
 
496
 
static AssuanError
 
583
static int
497
584
learn_status_cb (void *opaque, const char *line)
498
585
{
499
586
  struct learn_parm_s *parm = opaque;
549
636
                        NULL, NULL, NULL, NULL,
550
637
                        learn_status_cb, &parm);
551
638
  if (rc)
552
 
    return unlock_scd (ctrl, map_assuan_err (rc));
 
639
    return unlock_scd (ctrl, rc);
553
640
 
554
641
  return unlock_scd (ctrl, 0);
555
642
}
556
643
 
557
644
 
558
645
 
559
 
static AssuanError
 
646
static int
560
647
get_serialno_cb (void *opaque, const char *line)
561
648
{
562
649
  char **serialno = opaque;
572
659
  if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
573
660
    {
574
661
      if (*serialno)
575
 
        return ASSUAN_Unexpected_Status;
 
662
        return gpg_error (GPG_ERR_CONFLICT); /* Unexpected status line. */
576
663
      for (n=0,s=line; hexdigitp (s); s++, n++)
577
664
        ;
578
665
      if (!n || (n&1)|| !(spacep (s) || !*s) )
579
 
        return ASSUAN_Invalid_Status;
 
666
        return gpg_error (GPG_ERR_ASS_PARAMETER);
580
667
      *serialno = xtrymalloc (n+1);
581
668
      if (!*serialno)
582
 
        return ASSUAN_Out_Of_Core;
 
669
        return out_of_core ();
583
670
      memcpy (*serialno, line, n);
584
671
      (*serialno)[n] = 0;
585
672
    }
605
692
  if (rc)
606
693
    {
607
694
      xfree (serialno);
608
 
      return unlock_scd (ctrl, map_assuan_err (rc));
 
695
      return unlock_scd (ctrl, rc);
609
696
    }
610
697
  *r_serialno = serialno;
611
698
  return unlock_scd (ctrl, 0);
614
701
 
615
702
 
616
703
 
617
 
static AssuanError
 
704
static int
618
705
membuf_data_cb (void *opaque, const void *buffer, size_t length)
619
706
{
620
707
  membuf_t *data = opaque;
625
712
}
626
713
  
627
714
/* Handle the NEEDPIN inquiry. */
628
 
static AssuanError
 
715
static int
629
716
inq_needpin (void *opaque, const char *line)
630
717
{
631
718
  struct inq_needpin_s *parm = opaque;
642
729
      pinlen = 90;
643
730
      pin = gcry_malloc_secure (pinlen);
644
731
      if (!pin)
645
 
        return ASSUAN_Out_Of_Core;
 
732
        return out_of_core ();
646
733
 
647
734
      rc = parm->getpin_cb (parm->getpin_cb_arg, line, pin, pinlen);
648
 
      if (rc)
649
 
        rc = ASSUAN_Canceled;
650
735
      if (!rc)
651
736
        rc = assuan_send_data (parm->ctx, pin, pinlen);
652
737
      xfree (pin);
653
738
    }
654
 
  else if (!strncmp (line, "KEYPADINFO", 10) && (line[10] == ' ' || !line[10]))
 
739
  else if (!strncmp (line, "POPUPKEYPADPROMPT", 17)
 
740
           && (line[17] == ' ' || !line[17]))
655
741
    {
656
 
      size_t code;
657
 
      char *endp;
658
 
 
659
 
      code = strtoul (line+10, &endp, 10);
660
 
      line = endp;
 
742
      line += 17;
661
743
      while (*line == ' ')
662
744
        line++;
663
745
      
664
 
      rc = parm->getpin_cb (parm->getpin_cb_arg, line, NULL, code);
665
 
      if (rc)
666
 
        rc = ASSUAN_Canceled;
 
746
      rc = parm->getpin_cb (parm->getpin_cb_arg, line, NULL, 1);
 
747
    }
 
748
  else if (!strncmp (line, "DISMISSKEYPADPROMPT", 19)
 
749
           && (line[19] == ' ' || !line[19]))
 
750
    {
 
751
      rc = parm->getpin_cb (parm->getpin_cb_arg, "", NULL, 0);
 
752
    }
 
753
  else if (parm->passthru)
 
754
    {
 
755
      unsigned char *value;
 
756
      size_t valuelen;
 
757
      int rest;
 
758
      int needrest = !strncmp (line, "KEYDATA", 8);
 
759
 
 
760
      /* Pass the inquiry up to our caller.  We limit the maximum
 
761
         amount to an arbitrary value.  As we know that the KEYDATA
 
762
         enquiry is pretty sensitive we disable logging then */
 
763
      if ((rest = (needrest
 
764
                   && !assuan_get_flag (parm->passthru, ASSUAN_CONFIDENTIAL))))
 
765
        assuan_begin_confidential (parm->passthru);
 
766
      rc = assuan_inquire (parm->passthru, line, &value, &valuelen, 8096);
 
767
      if (rest)
 
768
        assuan_end_confidential (parm->passthru);
 
769
      if (!rc)
 
770
        {
 
771
          if ((rest = (needrest 
 
772
                       && !assuan_get_flag (parm->ctx, ASSUAN_CONFIDENTIAL))))
 
773
            assuan_begin_confidential (parm->ctx);
 
774
          rc = assuan_send_data (parm->ctx, value, valuelen);
 
775
          if (rest)
 
776
            assuan_end_confidential (parm->ctx);
 
777
          xfree (value);
 
778
        }
 
779
      else
 
780
        log_error ("error forwarding inquiry `%s': %s\n", 
 
781
                   line, gpg_strerror (rc));
667
782
    }
668
783
  else
669
784
    {
670
785
      log_error ("unsupported inquiry `%s'\n", line);
671
 
      rc = ASSUAN_Inquire_Unknown;
 
786
      rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
672
787
    }
673
788
 
674
789
  return rc;
708
823
  rc = assuan_transact (ctrl->scd_local->ctx, line,
709
824
                        NULL, NULL, NULL, NULL, NULL, NULL);
710
825
  if (rc)
711
 
    return unlock_scd (ctrl, map_assuan_err (rc));
 
826
    return unlock_scd (ctrl, rc);
712
827
 
713
828
  init_membuf (&data, 1024);
714
829
  inqparm.ctx = ctrl->scd_local->ctx;
715
830
  inqparm.getpin_cb = getpin_cb;
716
831
  inqparm.getpin_cb_arg = getpin_cb_arg;
 
832
  inqparm.passthru = 0;
717
833
  snprintf (line, DIM(line)-1, 
718
834
            ctrl->use_auth_call? "PKAUTH %s":"PKSIGN %s", keyid);
719
835
  line[DIM(line)-1] = 0;
724
840
  if (rc)
725
841
    {
726
842
      xfree (get_membuf (&data, &len));
727
 
      return unlock_scd (ctrl, map_assuan_err (rc));
 
843
      return unlock_scd (ctrl, rc);
728
844
    }
729
845
  sigbuf = get_membuf (&data, &sigbuflen);
730
846
 
778
894
  rc = assuan_transact (ctrl->scd_local->ctx, line,
779
895
                        NULL, NULL, NULL, NULL, NULL, NULL);
780
896
  if (rc)
781
 
    return unlock_scd (ctrl, map_assuan_err (rc));
 
897
    return unlock_scd (ctrl, rc);
782
898
 
783
899
  init_membuf (&data, 1024);
784
900
  inqparm.ctx = ctrl->scd_local->ctx;
785
901
  inqparm.getpin_cb = getpin_cb;
786
902
  inqparm.getpin_cb_arg = getpin_cb_arg;
 
903
  inqparm.passthru = 0;
787
904
  snprintf (line, DIM(line)-1, "PKDECRYPT %s", keyid);
788
905
  line[DIM(line)-1] = 0;
789
906
  rc = assuan_transact (ctrl->scd_local->ctx, line,
793
910
  if (rc)
794
911
    {
795
912
      xfree (get_membuf (&data, &len));
796
 
      return unlock_scd (ctrl, map_assuan_err (rc));
 
913
      return unlock_scd (ctrl, rc);
797
914
    }
798
915
  *r_buf = get_membuf (&data, r_buflen);
799
916
  if (!*r_buf)
829
946
  if (rc)
830
947
    {
831
948
      xfree (get_membuf (&data, &len));
832
 
      return unlock_scd (ctrl, map_assuan_err (rc));
 
949
      return unlock_scd (ctrl, rc);
833
950
    }
834
951
  *r_buf = get_membuf (&data, r_buflen);
835
952
  if (!*r_buf)
865
982
  if (rc)
866
983
    {
867
984
      xfree (get_membuf (&data, &len));
868
 
      return unlock_scd (ctrl, map_assuan_err (rc));
 
985
      return unlock_scd (ctrl, rc);
869
986
    }
870
987
  *r_buf = get_membuf (&data, &buflen);
871
988
  if (!*r_buf)
947
1064
  if (err)
948
1065
    return err;
949
1066
 
950
 
  err = map_assuan_err (assuan_transact (ctrl->scd_local->ctx, line,
951
 
                                         NULL, NULL, NULL, NULL,
952
 
                                         card_getattr_cb, &parm));
 
1067
  err = assuan_transact (ctrl->scd_local->ctx, line,
 
1068
                         NULL, NULL, NULL, NULL,
 
1069
                         card_getattr_cb, &parm);
953
1070
  if (!err && parm.error)
954
1071
    err = gpg_error_from_errno (parm.error);
955
1072
  
967
1084
 
968
1085
 
969
1086
 
970
 
static AssuanError
 
1087
static int
971
1088
pass_status_thru (void *opaque, const char *line)
972
1089
{
973
 
  ASSUAN_CONTEXT ctx = opaque;
 
1090
  assuan_context_t ctx = opaque;
974
1091
  char keyword[200];
975
1092
  int i;
976
1093
 
987
1104
  return 0;
988
1105
}
989
1106
 
990
 
static AssuanError
 
1107
static int
991
1108
pass_data_thru (void *opaque, const void *buffer, size_t length)
992
1109
{
993
 
  ASSUAN_CONTEXT ctx = opaque;
 
1110
  assuan_context_t ctx = opaque;
994
1111
 
995
1112
  assuan_send_data (ctx, buffer, length);
996
1113
  return 0;
999
1116
 
1000
1117
/* Send the line CMDLINE with command for the SCDdaemon to it and send
1001
1118
   all status messages back.  This command is used as a general quoting
1002
 
   mechanism to pass everything verbatim to SCDAEMOPN.  The PIN
1003
 
   inquirey is handled inside gpg-agent. */
 
1119
   mechanism to pass everything verbatim to SCDAEMON.  The PIN
 
1120
   inquiry is handled inside gpg-agent.  */
1004
1121
int
1005
1122
agent_card_scd (ctrl_t ctrl, const char *cmdline,
1006
1123
                int (*getpin_cb)(void *, const char *, char*, size_t),
1016
1133
  inqparm.ctx = ctrl->scd_local->ctx;
1017
1134
  inqparm.getpin_cb = getpin_cb;
1018
1135
  inqparm.getpin_cb_arg = getpin_cb_arg;
 
1136
  inqparm.passthru = assuan_context;
1019
1137
  rc = assuan_transact (ctrl->scd_local->ctx, cmdline,
1020
1138
                        pass_data_thru, assuan_context,
1021
1139
                        inq_needpin, &inqparm,
1022
1140
                        pass_status_thru, assuan_context);
1023
1141
  if (rc)
1024
1142
    {
1025
 
      return unlock_scd (ctrl, map_assuan_err (rc));
 
1143
      return unlock_scd (ctrl, rc);
1026
1144
    }
1027
1145
 
1028
1146
  return unlock_scd (ctrl, 0);