~ubuntu-branches/ubuntu/precise/gnupg2/precise-proposed

« back to all changes in this revision

Viewing changes to scd/command.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Mueller
  • Date: 2005-03-29 10:30:32 UTC
  • Revision ID: james.westby@ubuntu.com-20050329103032-sj42n2ain3ipx310
Tags: upstream-1.9.15
ImportĀ upstreamĀ versionĀ 1.9.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* command.c - SCdaemon command handler
 
2
 *      Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
3
 *
 
4
 * This file is part of GnuPG.
 
5
 *
 
6
 * GnuPG is free software; you can redistribute it and/or modify
 
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
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * GnuPG is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
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
 
19
 */
 
20
 
 
21
#include <config.h>
 
22
#include <errno.h>
 
23
#include <stdio.h>
 
24
#include <stdlib.h>
 
25
#include <string.h>
 
26
#include <ctype.h>
 
27
#include <unistd.h>
 
28
#include <signal.h>
 
29
 
 
30
#include <assuan.h>
 
31
 
 
32
#include "scdaemon.h"
 
33
#include <ksba.h>
 
34
#include "app-common.h"
 
35
#include "apdu.h" /* Required for apdu_*_reader (). */
 
36
 
 
37
/* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */
 
38
#define MAXLEN_PIN 100
 
39
 
 
40
 
 
41
/* We keep track of the primary client using scdaemon.  This one will
 
42
   for example receive signal on card change. */
 
43
static ctrl_t primary_connection;
 
44
 
 
45
 
 
46
#define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
 
47
 
 
48
/* Data used to associate an Assuan context with local server data */
 
49
struct server_local_s {
 
50
  ASSUAN_CONTEXT assuan_ctx;
 
51
  int event_signal;        /* Or 0 if not used. */
 
52
};
 
53
 
 
54
 
 
55
/* Check whether the option NAME appears in LINE */
 
56
static int
 
57
has_option (const char *line, const char *name)
 
58
{
 
59
  const char *s;
 
60
  int n = strlen (name);
 
61
 
 
62
  s = strstr (line, name);
 
63
  return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
 
64
}
 
65
 
 
66
 
 
67
/* Reset the card and free the application context.  With DO_CLOSE set
 
68
   to true, close the reader and don't do just a reset. */
 
69
static void
 
70
do_reset (ctrl_t ctrl, int do_close)
 
71
{
 
72
  if (ctrl->card_ctx)
 
73
    {
 
74
      card_close (ctrl->card_ctx);
 
75
      ctrl->card_ctx = NULL;
 
76
      xfree (ctrl->in_data.value);
 
77
      ctrl->in_data.value = NULL;
 
78
    }
 
79
  if (ctrl->app_ctx)
 
80
    {
 
81
      release_application (ctrl->app_ctx);
 
82
      ctrl->app_ctx = NULL;
 
83
    }
 
84
  if (ctrl->reader_slot != -1)
 
85
    {
 
86
      if (do_close || apdu_reset (ctrl->reader_slot))
 
87
        {
 
88
          apdu_close_reader (ctrl->reader_slot);
 
89
          ctrl->reader_slot = -1;
 
90
        }
 
91
    }
 
92
}
 
93
 
 
94
 
 
95
static void
 
96
reset_notify (ASSUAN_CONTEXT ctx)
 
97
{
 
98
  CTRL ctrl = assuan_get_pointer (ctx); 
 
99
 
 
100
  do_reset (ctrl, 0);
 
101
}
 
102
 
 
103
 
 
104
static int
 
105
option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
 
106
{
 
107
  ctrl_t ctrl = assuan_get_pointer (ctx);
 
108
 
 
109
  if (!strcmp (key, "event-signal"))
 
110
    {
 
111
      /* A value of 0 is allowed to reset the event signal. */
 
112
      int i = *value? atoi (value) : -1;
 
113
      if (i < 0)
 
114
        return ASSUAN_Parameter_Error;
 
115
      ctrl->server_local->event_signal = i;
 
116
    }
 
117
 
 
118
 return 0;
 
119
}
 
120
 
 
121
 
 
122
/* If the card has not yet been opened, do it.  Note that this
 
123
   function returns an Assuan error, so don't map the error a second
 
124
   time */
 
125
static AssuanError
 
126
open_card (ctrl_t ctrl, const char *apptype)
 
127
{
 
128
  int slot;
 
129
 
 
130
  if (ctrl->app_ctx)
 
131
    return 0; /* Already initialized for one specific application. */
 
132
  if (ctrl->card_ctx)
 
133
    return 0; /* Already initialized using a card context. */
 
134
 
 
135
  if (ctrl->reader_slot != -1)
 
136
    slot = ctrl->reader_slot;
 
137
  else
 
138
    slot = apdu_open_reader (opt.reader_port);
 
139
  ctrl->reader_slot = slot;
 
140
  if (slot != -1)
 
141
    ctrl->app_ctx = select_application (ctrl, slot, apptype);
 
142
  if (!ctrl->app_ctx)
 
143
    { /* No application found - fall back to old mode. */
 
144
      /* Note that we should rework the old code to use the
 
145
         application paradigma too. */
 
146
      int rc;
 
147
      
 
148
      /* If an APPTYPE was requested and it is not pkcs#15, we return
 
149
         an error here. */
 
150
      if (apptype && !(!strcmp (apptype, "P15") || !strcmp (apptype, "p15")))
 
151
        rc = gpg_error (GPG_ERR_NOT_SUPPORTED);
 
152
      else 
 
153
        rc = card_open (&ctrl->card_ctx);
 
154
      if (rc)
 
155
        return map_to_assuan_status (rc);
 
156
    }
 
157
  return 0;
 
158
}
 
159
 
 
160
 
 
161
/* Do the percent and plus/space unescaping in place and return the
 
162
   length of the valid buffer. */
 
163
static size_t
 
164
percent_plus_unescape (unsigned char *string)
 
165
{
 
166
  unsigned char *p = string;
 
167
  size_t n = 0;
 
168
 
 
169
  while (*string)
 
170
    {
 
171
      if (*string == '%' && string[1] && string[2])
 
172
        { 
 
173
          string++;
 
174
          *p++ = xtoi_2 (string);
 
175
          n++;
 
176
          string+= 2;
 
177
        }
 
178
      else if (*string == '+')
 
179
        {
 
180
          *p++ = ' ';
 
181
          n++;
 
182
          string++;
 
183
        }
 
184
      else
 
185
        {
 
186
          *p++ = *string++;
 
187
          n++;
 
188
        }
 
189
    }
 
190
 
 
191
  return n;
 
192
}
 
193
 
 
194
 
 
195
 
 
196
/* SERIALNO [APPTYPE] 
 
197
 
 
198
   Return the serial number of the card using a status reponse.  This
 
199
   functon should be used to check for the presence of a card.
 
200
 
 
201
   If APPTYPE is given, an application of that type is selected and an
 
202
   error is returned if the application is not supported or available.
 
203
   The default is to auto-select the application using a hardwired
 
204
   preference system.  Note, that a future extension to this function
 
205
   may allow to specify a list and order of applications to try.
 
206
 
 
207
   This function is special in that it can be used to reset the card.
 
208
   Most other functions will return an error when a card change has
 
209
   been detected and the use of this function is therefore required.
 
210
 
 
211
   Background: We want to keep the client clear of handling card
 
212
   changes between operations; i.e. the client can assume that all
 
213
   operations are done on the same card unless he calls this function.
 
214
 */
 
215
static int
 
216
cmd_serialno (ASSUAN_CONTEXT ctx, char *line)
 
217
{
 
218
  CTRL ctrl = assuan_get_pointer (ctx);
 
219
  int rc = 0;
 
220
  char *serial_and_stamp;
 
221
  char *serial;
 
222
  time_t stamp;
 
223
 
 
224
  if ((rc = open_card (ctrl, *line? line:NULL)))
 
225
    return rc;
 
226
 
 
227
  if (ctrl->app_ctx)
 
228
    rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
 
229
  else
 
230
    rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp);
 
231
  if (rc)
 
232
    return map_to_assuan_status (rc);
 
233
  rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp);
 
234
  xfree (serial);
 
235
  if (rc < 0)
 
236
    return ASSUAN_Out_Of_Core;
 
237
  rc = 0;
 
238
  assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
 
239
  free (serial_and_stamp);
 
240
  return 0;
 
241
}
 
242
 
 
243
 
 
244
 
 
245
 
 
246
/* LEARN [--force]
 
247
 
 
248
   Learn all useful information of the currently inserted card.  When
 
249
   used without the force options, the command might do an INQUIRE
 
250
   like this:
 
251
 
 
252
      INQUIRE KNOWNCARDP <hexstring_with_serialNumber> <timestamp>
 
253
 
 
254
   The client should just send an "END" if the processing should go on
 
255
   or a "CANCEL" to force the function to terminate with a Cancel
 
256
   error message.  The response of this command is a list of status
 
257
   lines formatted as this:
 
258
 
 
259
     S APPTYPE <apptype>
 
260
 
 
261
   This returns the type of the application, currently the strings:
 
262
 
 
263
       P15     = PKCS-15 structure used
 
264
       DINSIG  = DIN SIG
 
265
       OPENPGP = OpenPGP card
 
266
 
 
267
   are implemented.  These strings are aliases for the AID
 
268
 
 
269
     S KEYPAIRINFO <hexstring_with_keygrip> <hexstring_with_id>
 
270
 
 
271
   If there is no certificate yet stored on the card a single "X" is
 
272
   returned as the keygrip.  In addition to the keypair info, information
 
273
   about all certificates stored on the card is also returned:
 
274
 
 
275
     S CERTINFO <certtype> <hexstring_with_id>
 
276
 
 
277
   Where CERTTYPE is a number indicating the type of certificate:
 
278
      0   := Unknown
 
279
      100 := Regular X.509 cert
 
280
      101 := Trusted X.509 cert
 
281
      102 := Useful X.509 cert
 
282
      110 := Root CA cert (DINSIG)
 
283
 
 
284
   For certain cards, more information will be returned:
 
285
 
 
286
     S KEY-FPR <no> <hexstring>
 
287
 
 
288
   For OpenPGP cards this returns the stored fingerprints of the
 
289
   keys. This can be used check whether a key is available on the
 
290
   card.  NO may be 1, 2 or 3.
 
291
 
 
292
     S CA-FPR <no> <hexstring>
 
293
 
 
294
   Similar to above, these are the fingerprints of keys assumed to be
 
295
   ultimately trusted.
 
296
 
 
297
     S DISP-NAME <name_of_card_holder>
 
298
 
 
299
   The name of the card holder as stored on the card; percent
 
300
   escaping takes place, spaces are encoded as '+'
 
301
 
 
302
     S PUBKEY-URL <url>
 
303
 
 
304
   The URL to be used for locating the entire public key.
 
305
     
 
306
*/
 
307
static int
 
308
cmd_learn (ASSUAN_CONTEXT ctx, char *line)
 
309
{
 
310
  CTRL ctrl = assuan_get_pointer (ctx);
 
311
  int rc = 0;
 
312
  int idx;
 
313
 
 
314
  if ((rc = open_card (ctrl, NULL)))
 
315
    return rc;
 
316
 
 
317
  /* Unless the force option is used we try a shortcut by identifying
 
318
     the card using a serial number and inquiring the client with
 
319
     that. The client may choose to cancel the operation if he already
 
320
     knows about this card */
 
321
  {
 
322
    char *serial_and_stamp;
 
323
    char *serial;
 
324
    time_t stamp;
 
325
 
 
326
    if (ctrl->app_ctx)
 
327
      rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
 
328
    else
 
329
      rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp);
 
330
    if (rc)
 
331
      return map_to_assuan_status (rc);
 
332
    rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp);
 
333
    xfree (serial);
 
334
    if (rc < 0)
 
335
      return ASSUAN_Out_Of_Core;
 
336
    rc = 0;
 
337
    assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
 
338
 
 
339
    if (!has_option (line, "--force"))
 
340
      {
 
341
        char *command;
 
342
 
 
343
        rc = asprintf (&command, "KNOWNCARDP %s", serial_and_stamp);
 
344
        if (rc < 0)
 
345
          {
 
346
            free (serial_and_stamp);
 
347
            return ASSUAN_Out_Of_Core;
 
348
          }
 
349
        rc = 0;
 
350
        rc = assuan_inquire (ctx, command, NULL, NULL, 0); 
 
351
        free (command);  /* (must use standard free here) */
 
352
        if (rc)
 
353
          {
 
354
            if (rc != ASSUAN_Canceled)
 
355
              log_error ("inquire KNOWNCARDP failed: %s\n",
 
356
                         assuan_strerror (rc));
 
357
            free (serial_and_stamp);
 
358
            return rc; 
 
359
          }
 
360
        /* not canceled, so we have to proceeed */
 
361
      }
 
362
    free (serial_and_stamp);
 
363
  }
 
364
 
 
365
  /* If we are using the modern application paradigma, let the
 
366
     application print out its collection of useful status
 
367
     information. */
 
368
  if (!rc && ctrl->app_ctx)
 
369
    rc = app_write_learn_status (ctrl->app_ctx, ctrl);
 
370
 
 
371
  /* Return information about the certificates.  FIXME: Move this into
 
372
     an app-p15.c*/
 
373
  for (idx=0; !rc && !ctrl->app_ctx; idx++)
 
374
    {
 
375
      char *certid;
 
376
      int certtype;
 
377
 
 
378
      rc = card_enum_certs (ctrl->card_ctx, idx, &certid, &certtype);
 
379
      if (!rc)
 
380
        {
 
381
          char *buf;
 
382
 
 
383
          buf = xtrymalloc (40 + 1 + strlen (certid) + 1);
 
384
          if (!buf)
 
385
            rc = gpg_error (gpg_err_code_from_errno (errno));
 
386
          else
 
387
            {
 
388
              sprintf (buf, "%d %s", certtype, certid);
 
389
              assuan_write_status (ctx, "CERTINFO", buf);
 
390
              xfree (buf);
 
391
            }
 
392
        }
 
393
      xfree (certid);
 
394
    }
 
395
  if (rc == -1)
 
396
    rc = 0;
 
397
 
 
398
  /* Return information about the keys. FIXME: Move this into an
 
399
     app-p15.c */
 
400
  for (idx=0; !rc && !ctrl->app_ctx; idx++)
 
401
    {
 
402
      unsigned char keygrip[20];
 
403
      char *keyid;
 
404
      int no_cert = 0;
 
405
 
 
406
      rc = card_enum_keypairs (ctrl->card_ctx, idx, keygrip, &keyid);
 
407
      if (gpg_err_code (rc) == GPG_ERR_MISSING_CERT && keyid)
 
408
        {
 
409
          /* This does happen with an incomplete personalized
 
410
             card; i.e. during the time we have stored the key on the
 
411
             card but not stored the certificate; probably becuase it
 
412
             has not yet been received back from the CA.  Note that we
 
413
             must release KEYID in this case. */
 
414
          rc = 0; 
 
415
          no_cert = 1;
 
416
        }
 
417
      if (!rc)
 
418
        {
 
419
          char *buf, *p;
 
420
 
 
421
          buf = p = xtrymalloc (40 + 1 + strlen (keyid) + 1);
 
422
          if (!buf)
 
423
            rc = gpg_error (gpg_err_code_from_errno (errno));
 
424
          else
 
425
            {
 
426
              int i;
 
427
              
 
428
              if (no_cert)
 
429
                *p++ = 'X';
 
430
              else
 
431
                {
 
432
                  for (i=0; i < 20; i++, p += 2)
 
433
                    sprintf (p, "%02X", keygrip[i]);
 
434
                }
 
435
              *p++ = ' ';
 
436
              strcpy (p, keyid);
 
437
              assuan_write_status (ctx, "KEYPAIRINFO", buf);
 
438
              xfree (buf);
 
439
            }
 
440
        }
 
441
      xfree (keyid);
 
442
    }
 
443
  if (rc == -1)
 
444
    rc = 0;
 
445
 
 
446
  return map_to_assuan_status (rc);
 
447
}
 
448
 
 
449
 
 
450
 
 
451
/* READCERT <hexified_certid>
 
452
 
 
453
 */
 
454
static int
 
455
cmd_readcert (ASSUAN_CONTEXT ctx, char *line)
 
456
{
 
457
  CTRL ctrl = assuan_get_pointer (ctx);
 
458
  int rc;
 
459
  unsigned char *cert;
 
460
  size_t ncert;
 
461
 
 
462
  if ((rc = open_card (ctrl, NULL)))
 
463
    return rc;
 
464
 
 
465
  line = xstrdup (line); /* Need a copy of the line. */
 
466
  if (ctrl->app_ctx)
 
467
    {
 
468
      rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
 
469
      if (rc)
 
470
        log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
 
471
    }
 
472
  else
 
473
    {
 
474
      rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert);
 
475
      if (rc)
 
476
        log_error ("card_read_cert failed: %s\n", gpg_strerror (rc));
 
477
    }
 
478
  xfree (line);
 
479
  line = NULL;
 
480
  if (!rc)
 
481
    {
 
482
      rc = assuan_send_data (ctx, cert, ncert);
 
483
      xfree (cert);
 
484
      if (rc)
 
485
        return rc;
 
486
    }
 
487
 
 
488
  return map_to_assuan_status (rc);
 
489
}
 
490
 
 
491
 
 
492
/* READKEY <hexified_certid>
 
493
 
 
494
   Return the public key for the given cert or key ID as an standard
 
495
   S-Expression.  */
 
496
static int
 
497
cmd_readkey (ASSUAN_CONTEXT ctx, char *line)
 
498
{
 
499
  CTRL ctrl = assuan_get_pointer (ctx);
 
500
  int rc;
 
501
  unsigned char *cert = NULL;
 
502
  size_t ncert, n;
 
503
  ksba_cert_t kc = NULL;
 
504
  ksba_sexp_t p;
 
505
 
 
506
  if ((rc = open_card (ctrl, NULL)))
 
507
    return rc;
 
508
 
 
509
  line = xstrdup (line); /* Need a copy of the line. */
 
510
  if (ctrl->app_ctx)
 
511
    {
 
512
      rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
 
513
      if (rc)
 
514
        log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
 
515
    }
 
516
  else
 
517
    {
 
518
      rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert);
 
519
      if (rc)
 
520
        log_error ("card_read_cert failed: %s\n", gpg_strerror (rc));
 
521
    }
 
522
  xfree (line);
 
523
  line = NULL;
 
524
  if (rc)
 
525
    goto leave;
 
526
      
 
527
  rc = ksba_cert_new (&kc);
 
528
  if (rc)
 
529
    {
 
530
      xfree (cert);
 
531
      goto leave;
 
532
    }
 
533
  rc = ksba_cert_init_from_mem (kc, cert, ncert);
 
534
  if (rc)
 
535
    {
 
536
      log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc));
 
537
      goto leave;
 
538
    }
 
539
 
 
540
  p = ksba_cert_get_public_key (kc);
 
541
  if (!p)
 
542
    {
 
543
      rc = gpg_error (GPG_ERR_NO_PUBKEY);
 
544
      goto leave;
 
545
    }
 
546
 
 
547
  n = gcry_sexp_canon_len (p, 0, NULL, NULL);
 
548
  rc = assuan_send_data (ctx, p, n);
 
549
  rc = map_assuan_err (rc);
 
550
  xfree (p);
 
551
 
 
552
 
 
553
 leave:
 
554
  ksba_cert_release (kc);
 
555
  xfree (cert);
 
556
  return map_to_assuan_status (rc);
 
557
}
 
558
 
 
559
 
 
560
 
 
561
 
 
562
/* SETDATA <hexstring> 
 
563
 
 
564
   The client should use this command to tell us the data he want to
 
565
   sign.  */
 
566
static int
 
567
cmd_setdata (ASSUAN_CONTEXT ctx, char *line)
 
568
{
 
569
  CTRL ctrl = assuan_get_pointer (ctx);
 
570
  int n;
 
571
  char *p;
 
572
  unsigned char *buf;
 
573
 
 
574
  /* parse the hexstring */
 
575
  for (p=line,n=0; hexdigitp (p); p++, n++)
 
576
    ;
 
577
  if (*p)
 
578
    return set_error (Parameter_Error, "invalid hexstring");
 
579
  if (!n)
 
580
    return set_error (Parameter_Error, "no data given");
 
581
  if ((n&1))
 
582
    return set_error (Parameter_Error, "odd number of digits");
 
583
  n /= 2;
 
584
  buf = xtrymalloc (n);
 
585
  if (!buf)
 
586
    return ASSUAN_Out_Of_Core;
 
587
 
 
588
  ctrl->in_data.value = buf;
 
589
  ctrl->in_data.valuelen = n;
 
590
  for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++)
 
591
    buf[n] = xtoi_2 (p);
 
592
  return 0;
 
593
}
 
594
 
 
595
 
 
596
 
 
597
static int 
 
598
pin_cb (void *opaque, const char *info, char **retstr)
 
599
{
 
600
  ASSUAN_CONTEXT ctx = opaque;
 
601
  char *command;
 
602
  int rc;
 
603
  unsigned char *value;
 
604
  size_t valuelen;
 
605
 
 
606
  *retstr = NULL;
 
607
  log_debug ("asking for PIN '%s'\n", info);
 
608
 
 
609
  rc = asprintf (&command, "NEEDPIN %s", info);
 
610
  if (rc < 0)
 
611
    return gpg_error (gpg_err_code_from_errno (errno));
 
612
 
 
613
  /* FIXME: Write an inquire function which returns the result in
 
614
     secure memory */
 
615
  rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); 
 
616
  free (command);  
 
617
  if (rc)
 
618
    return map_assuan_err (rc);
 
619
 
 
620
  if (!valuelen || value[valuelen-1])
 
621
    {
 
622
      /* We require that the returned value is an UTF-8 string */
 
623
      xfree (value);
 
624
      return gpg_error (GPG_ERR_INV_RESPONSE);
 
625
    }
 
626
  *retstr = value;
 
627
  return 0;
 
628
}
 
629
 
 
630
 
 
631
/* PKSIGN <hexified_id>
 
632
 
 
633
 */
 
634
static int
 
635
cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
 
636
{
 
637
  CTRL ctrl = assuan_get_pointer (ctx);
 
638
  int rc;
 
639
  unsigned char *outdata;
 
640
  size_t outdatalen;
 
641
  char *keyidstr;
 
642
 
 
643
  if ((rc = open_card (ctrl, NULL)))
 
644
    return rc;
 
645
 
 
646
  /* We have to use a copy of the key ID because the function may use
 
647
     the pin_cb which in turn uses the assuan line buffer and thus
 
648
     overwriting the original line with the keyid */
 
649
  keyidstr = xtrystrdup (line);
 
650
  if (!keyidstr)
 
651
    return ASSUAN_Out_Of_Core;
 
652
  
 
653
  if (ctrl->app_ctx)
 
654
    rc = app_sign (ctrl->app_ctx,
 
655
                    keyidstr, GCRY_MD_SHA1,
 
656
                    pin_cb, ctx,
 
657
                    ctrl->in_data.value, ctrl->in_data.valuelen,
 
658
                    &outdata, &outdatalen);
 
659
  else  
 
660
    rc = card_sign (ctrl->card_ctx,
 
661
                    keyidstr, GCRY_MD_SHA1,
 
662
                    pin_cb, ctx,
 
663
                    ctrl->in_data.value, ctrl->in_data.valuelen,
 
664
                    &outdata, &outdatalen);
 
665
  xfree (keyidstr);
 
666
  if (rc)
 
667
    {
 
668
      log_error ("card_sign failed: %s\n", gpg_strerror (rc));
 
669
    }
 
670
  else
 
671
    {
 
672
      rc = assuan_send_data (ctx, outdata, outdatalen);
 
673
      xfree (outdata);
 
674
      if (rc)
 
675
        return rc; /* that is already an assuan error code */
 
676
    }
 
677
 
 
678
  return map_to_assuan_status (rc);
 
679
}
 
680
 
 
681
/* PKAUTH <hexified_id>
 
682
 
 
683
 */
 
684
static int
 
685
cmd_pkauth (ASSUAN_CONTEXT ctx, char *line)
 
686
{
 
687
  CTRL ctrl = assuan_get_pointer (ctx);
 
688
  int rc;
 
689
  unsigned char *outdata;
 
690
  size_t outdatalen;
 
691
  char *keyidstr;
 
692
 
 
693
  if ((rc = open_card (ctrl, NULL)))
 
694
    return rc;
 
695
 
 
696
  if (!ctrl->app_ctx)
 
697
    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
 
698
 
 
699
  /* We have to use a copy of the key ID because the function may use
 
700
     the pin_cb which in turn uses the assuan line buffer and thus
 
701
     overwriting the original line with the keyid */
 
702
  keyidstr = xtrystrdup (line);
 
703
  if (!keyidstr)
 
704
    return ASSUAN_Out_Of_Core;
 
705
  
 
706
  rc = app_auth (ctrl->app_ctx,
 
707
                 keyidstr,
 
708
                 pin_cb, ctx,
 
709
                 ctrl->in_data.value, ctrl->in_data.valuelen,
 
710
                 &outdata, &outdatalen);
 
711
  xfree (keyidstr);
 
712
  if (rc)
 
713
    {
 
714
      log_error ("app_auth_sign failed: %s\n", gpg_strerror (rc));
 
715
    }
 
716
  else
 
717
    {
 
718
      rc = assuan_send_data (ctx, outdata, outdatalen);
 
719
      xfree (outdata);
 
720
      if (rc)
 
721
        return rc; /* that is already an assuan error code */
 
722
    }
 
723
 
 
724
  return map_to_assuan_status (rc);
 
725
}
 
726
 
 
727
/* PKDECRYPT <hexified_id>
 
728
 
 
729
 */
 
730
static int
 
731
cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
 
732
{
 
733
  CTRL ctrl = assuan_get_pointer (ctx);
 
734
  int rc;
 
735
  unsigned char *outdata;
 
736
  size_t outdatalen;
 
737
  char *keyidstr;
 
738
 
 
739
  if ((rc = open_card (ctrl, NULL)))
 
740
    return rc;
 
741
 
 
742
  keyidstr = xtrystrdup (line);
 
743
  if (!keyidstr)
 
744
    return ASSUAN_Out_Of_Core;
 
745
  if (ctrl->app_ctx)
 
746
    rc = app_decipher (ctrl->app_ctx,
 
747
                        keyidstr, 
 
748
                        pin_cb, ctx,
 
749
                        ctrl->in_data.value, ctrl->in_data.valuelen,
 
750
                        &outdata, &outdatalen);
 
751
  else
 
752
    rc = card_decipher (ctrl->card_ctx,
 
753
                        keyidstr, 
 
754
                        pin_cb, ctx,
 
755
                        ctrl->in_data.value, ctrl->in_data.valuelen,
 
756
                        &outdata, &outdatalen);
 
757
  xfree (keyidstr);
 
758
  if (rc)
 
759
    {
 
760
      log_error ("card_create_signature failed: %s\n", gpg_strerror (rc));
 
761
    }
 
762
  else
 
763
    {
 
764
      rc = assuan_send_data (ctx, outdata, outdatalen);
 
765
      xfree (outdata);
 
766
      if (rc)
 
767
        return rc; /* that is already an assuan error code */
 
768
    }
 
769
 
 
770
  return map_to_assuan_status (rc);
 
771
}
 
772
 
 
773
 
 
774
/* GETATTR <name>
 
775
 
 
776
   This command is used to retrieve data from a smartcard.  The
 
777
   allowed names depend on the currently selected smartcard
 
778
   application.  NAME must be percent and '+' escaped.  The value is
 
779
   returned through status message, see the LESRN command for details.
 
780
 
 
781
   However, the current implementation assumes that Name is not escaped;
 
782
   this works as long as noone uses arbitrary escaping. 
 
783
 
 
784
*/
 
785
static int
 
786
cmd_getattr (ASSUAN_CONTEXT ctx, char *line)
 
787
{
 
788
  CTRL ctrl = assuan_get_pointer (ctx);
 
789
  int rc;
 
790
  char *keyword;
 
791
 
 
792
  if ((rc = open_card (ctrl, NULL)))
 
793
    return rc;
 
794
 
 
795
  keyword = line;
 
796
  for (; *line && !spacep (line); line++)
 
797
    ;
 
798
  if (*line)
 
799
      *line++ = 0;
 
800
 
 
801
  /* (We ignore any garbage for now.) */
 
802
 
 
803
  rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
 
804
 
 
805
  return map_to_assuan_status (rc);
 
806
}
 
807
 
 
808
 
 
809
/* SETATTR <name> <value> 
 
810
 
 
811
   This command is used to store data on a a smartcard.  The allowed
 
812
   names and values are depend on the currently selected smartcard
 
813
   application.  NAME and VALUE must be percent and '+' escaped.
 
814
 
 
815
   However, the curent implementation assumes that Name is not escaped;
 
816
   this works as long as noone uses arbitrary escaping. 
 
817
 
 
818
   A PIN will be requested for most NAMEs.  See the corresponding
 
819
   setattr function of the actually used application (app-*.c) for
 
820
   details.  */
 
821
static int
 
822
cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line)
 
823
{
 
824
  CTRL ctrl = assuan_get_pointer (ctx);
 
825
  int rc;
 
826
  char *keyword;
 
827
  int keywordlen;
 
828
  size_t nbytes;
 
829
  char *line, *linebuf;
 
830
 
 
831
  if ((rc = open_card (ctrl, NULL)))
 
832
    return rc;
 
833
 
 
834
  /* We need to use a copy of LINE, because PIN_CB uses the same
 
835
     context and thus reuses the Assuan provided LINE. */
 
836
  line = linebuf = xtrystrdup (orig_line);
 
837
  if (!line)
 
838
    return ASSUAN_Out_Of_Core;
 
839
 
 
840
  keyword = line;
 
841
  for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
 
842
    ;
 
843
  if (*line)
 
844
      *line++ = 0;
 
845
  while (spacep (line))
 
846
    line++;
 
847
  nbytes = percent_plus_unescape (line);
 
848
 
 
849
  rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx, line, nbytes);
 
850
  xfree (linebuf);
 
851
 
 
852
  return map_to_assuan_status (rc);
 
853
}
 
854
 
 
855
/* GENKEY [--force] <no>
 
856
 
 
857
   Generate a key on-card identified by NO, which is application
 
858
   specific.  Return values are application specific.  For OpenPGP
 
859
   cards 2 status lines are returned:
 
860
 
 
861
     S KEY-FPR  <hexstring>
 
862
     S KEY-CREATED-AT <seconds_since_epoch>
 
863
     S KEY-DATA [p|n] <hexdata>
 
864
     
 
865
 
 
866
   --force is required to overwriet an already existing key.  The
 
867
   KEY-CREATED-AT is required for further processing because it is
 
868
   part of the hashed key material for the fingerprint.
 
869
 
 
870
   The public part of the key can also later be retrieved using the
 
871
   READKEY command.
 
872
 
 
873
 */
 
874
static int
 
875
cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
 
876
{
 
877
  CTRL ctrl = assuan_get_pointer (ctx);
 
878
  int rc;
 
879
  char *keyno;
 
880
  int force = has_option (line, "--force");
 
881
 
 
882
  /* Skip over options. */
 
883
  while ( *line == '-' && line[1] == '-' )
 
884
    {
 
885
      while (*line && !spacep (line))
 
886
        line++;
 
887
      while (spacep (line))
 
888
        line++;
 
889
    }
 
890
  if (!*line)
 
891
    return set_error (Parameter_Error, "no key number given");
 
892
  keyno = line;
 
893
  while (*line && !spacep (line))
 
894
    line++;
 
895
  *line = 0;
 
896
 
 
897
  if ((rc = open_card (ctrl, NULL)))
 
898
    return rc;
 
899
 
 
900
  if (!ctrl->app_ctx)
 
901
    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
 
902
 
 
903
  keyno = xtrystrdup (keyno);
 
904
  if (!keyno)
 
905
    return ASSUAN_Out_Of_Core;
 
906
  rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0, pin_cb, ctx);
 
907
  xfree (keyno);
 
908
  return map_to_assuan_status (rc);
 
909
}
 
910
 
 
911
 
 
912
/* RANDOM <nbytes>
 
913
 
 
914
   Get NBYTES of random from the card and send them back as data. 
 
915
*/
 
916
static int
 
917
cmd_random (ASSUAN_CONTEXT ctx, char *line)
 
918
{
 
919
  CTRL ctrl = assuan_get_pointer (ctx);
 
920
  int rc;
 
921
  size_t nbytes;
 
922
  unsigned char *buffer;
 
923
 
 
924
  if (!*line)
 
925
    return set_error (Parameter_Error, "number of requested bytes missing");
 
926
  nbytes = strtoul (line, NULL, 0);
 
927
 
 
928
  if ((rc = open_card (ctrl, NULL)))
 
929
    return rc;
 
930
 
 
931
  if (!ctrl->app_ctx)
 
932
    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
 
933
 
 
934
  buffer = xtrymalloc (nbytes);
 
935
  if (!buffer)
 
936
    return ASSUAN_Out_Of_Core;
 
937
 
 
938
  rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer);
 
939
  if (!rc)
 
940
    {
 
941
      rc = assuan_send_data (ctx, buffer, nbytes);
 
942
      xfree (buffer);
 
943
      return rc; /* that is already an assuan error code */
 
944
    }
 
945
  xfree (buffer);
 
946
 
 
947
  return map_to_assuan_status (rc);
 
948
}
 
949
 
 
950
 
 
951
/* PASSWD [--reset] <chvno>
 
952
  
 
953
   Change the PIN or reset thye retry counter of the card holder
 
954
   verfication vector CHVNO. */
 
955
static int
 
956
cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
 
957
{
 
958
  CTRL ctrl = assuan_get_pointer (ctx);
 
959
  int rc;
 
960
  char *chvnostr;
 
961
  int reset_mode = has_option (line, "--reset");
 
962
 
 
963
  /* Skip over options. */
 
964
  while (*line == '-' && line[1] == '-')
 
965
    {
 
966
      while (*line && !spacep (line))
 
967
        line++;
 
968
      while (spacep (line))
 
969
        line++;
 
970
    }
 
971
  if (!*line)
 
972
    return set_error (Parameter_Error, "no CHV number given");
 
973
  chvnostr = line;
 
974
  while (*line && !spacep (line))
 
975
    line++;
 
976
  *line = 0;
 
977
 
 
978
  if ((rc = open_card (ctrl, NULL)))
 
979
    return rc;
 
980
 
 
981
  if (!ctrl->app_ctx)
 
982
    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
 
983
  
 
984
  chvnostr = xtrystrdup (chvnostr);
 
985
  if (!chvnostr)
 
986
    return ASSUAN_Out_Of_Core;
 
987
  rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, reset_mode, pin_cb, ctx);
 
988
  if (rc)
 
989
    log_error ("command passwd failed: %s\n", gpg_strerror (rc));
 
990
  xfree (chvnostr);
 
991
  return map_to_assuan_status (rc);
 
992
}
 
993
 
 
994
 
 
995
/* CHECKPIN <hexified_id>
 
996
 
 
997
 */
 
998
static int
 
999
cmd_checkpin (ASSUAN_CONTEXT ctx, char *line)
 
1000
{
 
1001
  CTRL ctrl = assuan_get_pointer (ctx);
 
1002
  int rc;
 
1003
  char *keyidstr;
 
1004
 
 
1005
  if ((rc = open_card (ctrl, NULL)))
 
1006
    return rc;
 
1007
 
 
1008
  if (!ctrl->app_ctx)
 
1009
    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
 
1010
 
 
1011
  /* We have to use a copy of the key ID because the function may use
 
1012
     the pin_cb which in turn uses the assuan line buffer and thus
 
1013
     overwriting the original line with the keyid. */
 
1014
  keyidstr = xtrystrdup (line);
 
1015
  if (!keyidstr)
 
1016
    return ASSUAN_Out_Of_Core;
 
1017
  
 
1018
  rc = app_check_pin (ctrl->app_ctx,
 
1019
                      keyidstr,
 
1020
                      pin_cb, ctx);
 
1021
  xfree (keyidstr);
 
1022
  if (rc)
 
1023
    log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
 
1024
 
 
1025
  return map_to_assuan_status (rc);
 
1026
}
 
1027
 
 
1028
 
 
1029
 
 
1030
 
 
1031
 
 
1032
/* Tell the assuan library about our commands */
 
1033
static int
 
1034
register_commands (ASSUAN_CONTEXT ctx)
 
1035
{
 
1036
  static struct {
 
1037
    const char *name;
 
1038
    int (*handler)(ASSUAN_CONTEXT, char *line);
 
1039
  } table[] = {
 
1040
    { "SERIALNO",     cmd_serialno },
 
1041
    { "LEARN",        cmd_learn },
 
1042
    { "READCERT",     cmd_readcert },
 
1043
    { "READKEY",      cmd_readkey },
 
1044
    { "SETDATA",      cmd_setdata },
 
1045
    { "PKSIGN",       cmd_pksign },
 
1046
    { "PKAUTH",       cmd_pkauth },
 
1047
    { "PKDECRYPT",    cmd_pkdecrypt },
 
1048
    { "INPUT",        NULL }, 
 
1049
    { "OUTPUT",       NULL }, 
 
1050
    { "GETATTR",      cmd_getattr },
 
1051
    { "SETATTR",      cmd_setattr },
 
1052
    { "GENKEY",       cmd_genkey },
 
1053
    { "RANDOM",       cmd_random },
 
1054
    { "PASSWD",       cmd_passwd },
 
1055
    { "CHECKPIN",     cmd_checkpin },
 
1056
    { NULL }
 
1057
  };
 
1058
  int i, rc;
 
1059
 
 
1060
  for (i=0; table[i].name; i++)
 
1061
    {
 
1062
      rc = assuan_register_command (ctx, table[i].name, table[i].handler);
 
1063
      if (rc)
 
1064
        return rc;
 
1065
    } 
 
1066
  assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
 
1067
 
 
1068
  assuan_register_reset_notify (ctx, reset_notify);
 
1069
  assuan_register_option_handler (ctx, option_handler);
 
1070
  return 0;
 
1071
}
 
1072
 
 
1073
 
 
1074
/* Startup the server.  If LISTEN_FD is given as -1, this is simple
 
1075
   piper server, otherwise it is a regular server */
 
1076
void
 
1077
scd_command_handler (int listen_fd)
 
1078
{
 
1079
  int rc;
 
1080
  ASSUAN_CONTEXT ctx;
 
1081
  struct server_control_s ctrl;
 
1082
 
 
1083
  memset (&ctrl, 0, sizeof ctrl);
 
1084
  scd_init_default_ctrl (&ctrl);
 
1085
  
 
1086
  if (listen_fd == -1)
 
1087
    {
 
1088
      int filedes[2];
 
1089
 
 
1090
      filedes[0] = 0;
 
1091
      filedes[1] = 1;
 
1092
      rc = assuan_init_pipe_server (&ctx, filedes);
 
1093
    }
 
1094
  else
 
1095
    {
 
1096
      rc = assuan_init_socket_server (&ctx, listen_fd);
 
1097
    }
 
1098
  if (rc)
 
1099
    {
 
1100
      log_error ("failed to initialize the server: %s\n",
 
1101
                 assuan_strerror(rc));
 
1102
      scd_exit (2);
 
1103
    }
 
1104
  rc = register_commands (ctx);
 
1105
  if (rc)
 
1106
    {
 
1107
      log_error ("failed to register commands with Assuan: %s\n",
 
1108
                 assuan_strerror(rc));
 
1109
      scd_exit (2);
 
1110
    }
 
1111
  assuan_set_pointer (ctx, &ctrl);
 
1112
  ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
 
1113
  ctrl.server_local->assuan_ctx = ctx;
 
1114
 
 
1115
  if (DBG_ASSUAN)
 
1116
    assuan_set_log_stream (ctx, log_get_stream ());
 
1117
 
 
1118
  /* Store the primary connection's assuan context. */
 
1119
  if (!primary_connection)
 
1120
    primary_connection = &ctrl;
 
1121
 
 
1122
  /* We open the reader right at startup so that the ticker is able to
 
1123
     update the status file. */
 
1124
  if (ctrl.reader_slot == -1)
 
1125
    ctrl.reader_slot = apdu_open_reader (opt.reader_port);
 
1126
 
 
1127
  /* Command processing loop. */
 
1128
  for (;;)
 
1129
    {
 
1130
      rc = assuan_accept (ctx);
 
1131
      if (rc == -1)
 
1132
        {
 
1133
          break;
 
1134
        }
 
1135
      else if (rc)
 
1136
        {
 
1137
          log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
 
1138
          break;
 
1139
        }
 
1140
      
 
1141
      rc = assuan_process (ctx);
 
1142
      if (rc)
 
1143
        {
 
1144
          log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
 
1145
          continue;
 
1146
        }
 
1147
    }
 
1148
 
 
1149
  /* The next client will be the primary conenction if this one
 
1150
     terminates. */
 
1151
  if (primary_connection == &ctrl)
 
1152
    primary_connection = NULL;
 
1153
 
 
1154
  do_reset (&ctrl, 1); /* Cleanup. */
 
1155
 
 
1156
  assuan_deinit_server (ctx);
 
1157
}
 
1158
 
 
1159
 
 
1160
/* Send a line with status information via assuan and escape all given
 
1161
   buffers. The variable elements are pairs of (char *, size_t),
 
1162
   terminated with a (NULL, 0). */
 
1163
void
 
1164
send_status_info (CTRL ctrl, const char *keyword, ...)
 
1165
{
 
1166
  va_list arg_ptr;
 
1167
  const unsigned char *value;
 
1168
  size_t valuelen;
 
1169
  char buf[950], *p;
 
1170
  size_t n;
 
1171
  ASSUAN_CONTEXT ctx = ctrl->server_local->assuan_ctx;
 
1172
  
 
1173
  va_start (arg_ptr, keyword);
 
1174
 
 
1175
  p = buf; 
 
1176
  n = 0;
 
1177
  while ( (value = va_arg (arg_ptr, const unsigned char *)) )
 
1178
    {
 
1179
      valuelen = va_arg (arg_ptr, size_t);
 
1180
      if (!valuelen)
 
1181
        continue; /* empty buffer */
 
1182
      if (n)
 
1183
        {
 
1184
          *p++ = ' ';
 
1185
          n++;
 
1186
        }
 
1187
      for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
 
1188
        {
 
1189
          if (*value < ' ' || *value == '+')
 
1190
            {
 
1191
              sprintf (p, "%%%02X", *value);
 
1192
              p += 3;
 
1193
            }
 
1194
          else if (*value == ' ')
 
1195
            *p++ = '+';
 
1196
          else
 
1197
            *p++ = *value;
 
1198
        }
 
1199
    }
 
1200
  *p = 0;
 
1201
  assuan_write_status (ctx, keyword, buf);
 
1202
 
 
1203
  va_end (arg_ptr);
 
1204
}
 
1205
 
 
1206
 
 
1207
 
 
1208
void
 
1209
scd_update_reader_status_file (void)
 
1210
{
 
1211
  static struct {
 
1212
    int any;
 
1213
    unsigned int status;
 
1214
    unsigned int changed;
 
1215
  } last[10];
 
1216
  int slot;
 
1217
  int used;
 
1218
  unsigned int status, changed;
 
1219
 
 
1220
  /* Note, that we only try to get the status, becuase it does not
 
1221
     make sense to wait here for a operation to complete.  If we are
 
1222
     so busy working with the card, delays in the status file updated
 
1223
     are should be acceptable. */
 
1224
  for (slot=0; (slot < DIM(last)
 
1225
                &&!apdu_enum_reader (slot, &used)); slot++)
 
1226
    if (used && !apdu_get_status (slot, 0, &status, &changed))
 
1227
      {
 
1228
        if (!last[slot].any || last[slot].status != status
 
1229
            || last[slot].changed != changed )
 
1230
          {
 
1231
            char *fname;
 
1232
            char templ[50];
 
1233
            FILE *fp;
 
1234
 
 
1235
            last[slot].any = 1;
 
1236
            last[slot].status = status;
 
1237
            last[slot].changed = changed;
 
1238
 
 
1239
            log_info ("updating status of slot %d to 0x%04X\n", slot, status);
 
1240
            
 
1241
            sprintf (templ, "reader_%d.status", slot);
 
1242
            fname = make_filename (opt.homedir, templ, NULL );
 
1243
            fp = fopen (fname, "w");
 
1244
            if (fp)
 
1245
              {
 
1246
                fprintf (fp, "%s\n",
 
1247
                         (status & 1)? "USABLE":
 
1248
                         (status & 4)? "ACTIVE":
 
1249
                         (status & 2)? "PRESENT": "NOCARD");
 
1250
                fclose (fp);
 
1251
              }
 
1252
            xfree (fname);
 
1253
 
 
1254
            /* Send a signal to the primary client, if any. */
 
1255
            if (primary_connection && primary_connection->server_local
 
1256
                && primary_connection->server_local->assuan_ctx)
 
1257
              {
 
1258
                pid_t pid = assuan_get_pid (primary_connection
 
1259
                                            ->server_local->assuan_ctx);
 
1260
                int signo = primary_connection->server_local->event_signal;
 
1261
 
 
1262
                log_info ("client pid is %d, sending signal %d\n", pid, signo);
 
1263
 
 
1264
#ifndef HAVE_W32_SYSTEM
 
1265
                if (pid != (pid_t)(-1) && pid && signo > 0)
 
1266
                  kill (pid, signo);
 
1267
#endif
 
1268
              }
 
1269
          }
 
1270
      }
 
1271
}