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

« back to all changes in this revision

Viewing changes to sm/call-dirmngr.c

  • Committer: Bazaar Package Importer
  • Author(s): Eric Dorland
  • Date: 2009-03-08 22:46:47 UTC
  • mfrom: (1.1.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20090308224647-gq17gatcl71lrc2k
Tags: 2.0.11-1
* New upstream release. (Closes: #496663)
* debian/control: Make the description a little more distinctive than
  gnupg v1's. Thanks Jari Aalto. (Closes: #496323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
44
44
 
45
45
 
46
46
 
 
47
/* fixme: We need a context for each thread or serialize the access to
 
48
   the dirmngr.  */
47
49
static assuan_context_t dirmngr_ctx = NULL;
 
50
static assuan_context_t dirmngr2_ctx = NULL;
 
51
 
 
52
static int dirmngr_ctx_locked;
 
53
static int dirmngr2_ctx_locked;
 
54
 
48
55
static int force_pipe_server = 0;
49
56
 
50
57
struct inq_certificate_parm_s {
 
58
  ctrl_t ctrl;
51
59
  assuan_context_t ctx;
52
60
  ksba_cert_t cert;
53
61
  ksba_cert_t issuer_cert;
134
142
}
135
143
 
136
144
 
137
 
/* This fucntion prepares the dirmngr for a new session.  The
 
145
/* This function prepares the dirmngr for a new session.  The
138
146
   audit-events option is used so that other dirmngr clients won't get
139
147
   disturbed by such events.  */
140
148
static void
141
149
prepare_dirmngr (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t err)
142
150
{
143
 
  if (!ctrl->dirmngr_seen)
144
 
    {
145
 
      ctrl->dirmngr_seen = 1;
146
 
      if (!err)
147
 
        {
148
 
          err = assuan_transact (ctx, "OPTION audit-events=1",
149
 
                                 NULL, NULL, NULL, NULL, NULL, NULL);
150
 
          if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
151
 
            err = 0;  /* Allow the use of old dirmngr versions.  */
152
 
        }
153
 
      audit_log_ok (ctrl->audit, AUDIT_DIRMNGR_READY, err);
 
151
  struct keyserver_spec *server;
 
152
 
 
153
  if (!err)
 
154
    {
 
155
      err = assuan_transact (ctx, "OPTION audit-events=1",
 
156
                             NULL, NULL, NULL, NULL, NULL, NULL);
 
157
      if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
 
158
        err = 0;  /* Allow the use of old dirmngr versions.  */
 
159
    }
 
160
  audit_log_ok (ctrl->audit, AUDIT_DIRMNGR_READY, err);
 
161
 
 
162
  server = opt.keyserver;
 
163
  while (server)
 
164
    {
 
165
      char line[ASSUAN_LINELENGTH];
 
166
      char *user = server->user ? server->user : "";
 
167
      char *pass = server->pass ? server->pass : "";
 
168
      char *base = server->base ? server->base : "";
 
169
      
 
170
      snprintf (line, DIM (line) - 1, "LDAPSERVER %s:%i:%s:%s:%s",
 
171
                server->host, server->port, user, pass, base);
 
172
      line[DIM (line) - 1] = 0;
 
173
 
 
174
      err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
 
175
      if (gpg_err_code (err) == GPG_ERR_ASS_UNKNOWN_CMD)
 
176
        err = 0;  /* Allow the use of old dirmngr versions.  */
 
177
 
 
178
      server = server->next;
154
179
    }
155
180
}
156
181
 
159
184
/* Try to connect to the agent via socket or fork it off and work by
160
185
   pipes.  Handle the server's initial greeting */
161
186
static int
162
 
start_dirmngr (ctrl_t ctrl)
 
187
start_dirmngr_ext (ctrl_t ctrl, assuan_context_t *ctx_r)
163
188
{
164
189
  int rc;
165
190
  char *infostr, *p;
169
194
  if (opt.disable_dirmngr)
170
195
    return gpg_error (GPG_ERR_NO_DIRMNGR);
171
196
 
172
 
  if (dirmngr_ctx)
173
 
    {
174
 
      prepare_dirmngr (ctrl, dirmngr_ctx, 0);
175
 
      return 0; /* fixme: We need a context for each thread or serialize
176
 
                   the access to the dirmngr */
177
 
    }
 
197
  if (*ctx_r)
 
198
    return 0;
 
199
 
178
200
  /* Note: if you change this to multiple connections, you also need
179
201
     to take care of the implicit option sending caching. */
180
202
 
245
267
              log_error (_("malformed DIRMNGR_INFO environment variable\n"));
246
268
              xfree (infostr);
247
269
              force_pipe_server = 1;
248
 
              return start_dirmngr (ctrl);
 
270
              return start_dirmngr_ext (ctrl, ctx_r);
249
271
            }
250
272
          *p++ = 0;
251
273
          pid = atoi (p);
258
280
                         prot);
259
281
              xfree (infostr);
260
282
              force_pipe_server = 1;
261
 
              return start_dirmngr (ctrl);
 
283
              return start_dirmngr_ext (ctrl, ctx_r);
262
284
            }
263
285
        }
264
286
      else
274
296
#ifndef HAVE_W32_SYSTEM
275
297
      if (gpg_err_code (rc) == GPG_ERR_ASS_CONNECT_FAILED)
276
298
        {
277
 
          log_error (_("can't connect to the dirmngr - trying fall back\n"));
 
299
          log_info (_("can't connect to the dirmngr - trying fall back\n"));
278
300
          force_pipe_server = 1;
279
 
          return start_dirmngr (ctrl);
 
301
          return start_dirmngr_ext (ctrl, ctx_r);
280
302
        }
281
303
#endif /*!HAVE_W32_SYSTEM*/
282
304
    }
288
310
      log_error ("can't connect to the dirmngr: %s\n", gpg_strerror (rc));
289
311
      return gpg_error (GPG_ERR_NO_DIRMNGR);
290
312
    }
291
 
  dirmngr_ctx = ctx;
 
313
  *ctx_r = ctx;
292
314
 
293
315
  if (DBG_ASSUAN)
294
316
    log_debug ("connection to dirmngr established\n");
296
318
}
297
319
 
298
320
 
 
321
static int
 
322
start_dirmngr (ctrl_t ctrl)
 
323
{
 
324
  gpg_error_t err;
 
325
 
 
326
  assert (! dirmngr_ctx_locked);
 
327
  dirmngr_ctx_locked = 1;
 
328
 
 
329
  err = start_dirmngr_ext (ctrl, &dirmngr_ctx);
 
330
  /* We do not check ERR but the existance of a context because the
 
331
     error might come from a failed command send to the dirmngr.
 
332
     Fixme: Why don't we close the drimngr context if we encountered
 
333
     an error in prepare_dirmngr?  */
 
334
  if (!dirmngr_ctx)
 
335
    dirmngr_ctx_locked = 0;
 
336
  return err;  
 
337
}
 
338
 
 
339
 
 
340
static void
 
341
release_dirmngr (ctrl_t ctrl)
 
342
{
 
343
  (void)ctrl;
 
344
 
 
345
  if (!dirmngr_ctx_locked)
 
346
    log_error ("WARNING: trying to release a non-locked dirmngr ctx\n");
 
347
  dirmngr_ctx_locked = 0;
 
348
}
 
349
 
 
350
 
 
351
static int
 
352
start_dirmngr2 (ctrl_t ctrl)
 
353
{
 
354
  gpg_error_t err;
 
355
 
 
356
  assert (! dirmngr2_ctx_locked);
 
357
  dirmngr2_ctx_locked = 1;
 
358
 
 
359
  err = start_dirmngr_ext (ctrl, &dirmngr2_ctx);
 
360
  if (!dirmngr2_ctx)
 
361
    dirmngr2_ctx_locked = 0;
 
362
  return err;
 
363
}
 
364
 
 
365
 
 
366
static void
 
367
release_dirmngr2 (ctrl_t ctrl)
 
368
{
 
369
  (void)ctrl;
 
370
 
 
371
  if (!dirmngr2_ctx_locked)
 
372
    log_error ("WARNING: trying to release a non-locked dirmngr2 ctx\n");
 
373
  dirmngr2_ctx_locked = 0;
 
374
}
 
375
 
 
376
 
299
377
 
300
378
/* Handle a SENDCERT inquiry. */
301
379
static int
331
409
      line += 14;
332
410
      issuer_mode = 1;
333
411
    }
 
412
  else if (!strncmp (line, "ISTRUSTED", 9) && (line[9]==' ' || !line[9]))
 
413
    {
 
414
      /* The server is asking us whether the certificate is a trusted
 
415
         root certificate.  */
 
416
      const char *s;
 
417
      size_t n;
 
418
      char fpr[41];
 
419
      struct rootca_flags_s rootca_flags;
 
420
 
 
421
      line += 9;
 
422
      while (*line == ' ')
 
423
        line++;
 
424
 
 
425
      for (s=line,n=0; hexdigitp (s); s++, n++)
 
426
        ;
 
427
      if (*s || n != 40)
 
428
        return gpg_error (GPG_ERR_ASS_PARAMETER);
 
429
      for (s=line, n=0; n < 40; s++, n++)
 
430
        fpr[n] = (*s >= 'a')? (*s & 0xdf): *s;
 
431
      fpr[n] = 0;
 
432
      
 
433
      if (!gpgsm_agent_istrusted (parm->ctrl, NULL, fpr, &rootca_flags))
 
434
        rc = assuan_send_data (parm->ctx, "1", 1);
 
435
      else
 
436
        rc = 0;
 
437
      return rc;
 
438
    }
334
439
  else
335
440
    {
336
441
      log_error ("unsupported inquiry `%s'\n", line);
464
569
      if (!certid)
465
570
        {
466
571
          log_error ("error getting the certificate ID\n");
 
572
          release_dirmngr (ctrl);
467
573
          return gpg_error (GPG_ERR_GENERAL);
468
574
        }
469
575
    }
477
583
    }
478
584
 
479
585
  parm.ctx = dirmngr_ctx;
 
586
  parm.ctrl = ctrl;
480
587
  parm.cert = cert;
481
588
  parm.issuer_cert = issuer_cert;
482
589
 
563
670
          ksba_cert_release (rspcert);
564
671
        }
565
672
    }
 
673
  release_dirmngr (ctrl);
566
674
  return rc;
567
675
}
568
676
 
703
811
}
704
812
 
705
813
 
706
 
/* Run the Directroy Managers lookup command using the pattern
 
814
/* Run the Directory Manager's lookup command using the pattern
707
815
   compiled from the strings given in NAMES.  The caller must provide
708
816
   the callback CB which will be passed cert by cert.  Note that CTRL
709
817
   is optional.  With CACHE_ONLY the dirmngr will search only its own
717
825
  char line[ASSUAN_LINELENGTH];
718
826
  struct lookup_parm_s parm;
719
827
  size_t len;
 
828
  assuan_context_t ctx;
720
829
 
721
 
  rc = start_dirmngr (ctrl);
722
 
  if (rc)
723
 
    return rc;
 
830
  /* The lookup function can be invoked from the callback of a lookup
 
831
     function, for example to walk the chain.  */
 
832
  if (!dirmngr_ctx_locked)
 
833
    {
 
834
      rc = start_dirmngr (ctrl);
 
835
      if (rc)
 
836
        return rc;
 
837
      ctx = dirmngr_ctx;
 
838
    }
 
839
  else if (!dirmngr2_ctx_locked)
 
840
    {
 
841
      rc = start_dirmngr2 (ctrl);
 
842
      if (rc)
 
843
        return rc;
 
844
      ctx = dirmngr2_ctx;
 
845
    }
 
846
  else
 
847
    {
 
848
      log_fatal ("both dirmngr contexts are in use\n");
 
849
    }
724
850
 
725
851
  pattern = pattern_from_strlist (names);
726
852
  if (!pattern)
727
 
    return out_of_core ();
 
853
    {
 
854
      if (ctx == dirmngr_ctx)
 
855
        release_dirmngr (ctrl);
 
856
      else
 
857
        release_dirmngr2 (ctrl);
 
858
 
 
859
      return out_of_core ();
 
860
    }
728
861
  snprintf (line, DIM(line)-1, "LOOKUP%s %s", 
729
862
            cache_only? " --cache-only":"", pattern);
730
863
  line[DIM(line)-1] = 0;
731
864
  xfree (pattern);
732
865
 
733
866
  parm.ctrl = ctrl;
734
 
  parm.ctx = dirmngr_ctx;
 
867
  parm.ctx = ctx;
735
868
  parm.cb = cb;
736
869
  parm.cb_value = cb_value;
737
870
  parm.error = 0;
738
871
  init_membuf (&parm.data, 4096);
739
872
 
740
 
  rc = assuan_transact (dirmngr_ctx, line, lookup_cb, &parm,
 
873
  rc = assuan_transact (ctx, line, lookup_cb, &parm,
741
874
                        NULL, NULL, lookup_status_cb, &parm);
742
875
  xfree (get_membuf (&parm.data, &len));
 
876
 
 
877
  if (ctx == dirmngr_ctx)
 
878
    release_dirmngr (ctrl);
 
879
  else
 
880
    release_dirmngr2 (ctrl);
 
881
 
743
882
  if (rc)
744
 
    return rc;
 
883
      return rc;
745
884
  return parm.error;
746
885
}
747
886
 
753
892
static int
754
893
run_command_cb (void *opaque, const void *buffer, size_t length)
755
894
{
 
895
  (void)opaque;
 
896
 
756
897
  if (buffer)
757
898
    {
758
899
      if ( fwrite (buffer, length, 1, stdout) != 1 )
860
1001
    len += 1 + 3*strlen (argv[i]); /* enough space for percent escaping */
861
1002
  line = xtrymalloc (len);
862
1003
  if (!line)
863
 
    return out_of_core ();
 
1004
    {
 
1005
      release_dirmngr (ctrl);
 
1006
      return out_of_core ();
 
1007
    }
864
1008
 
865
1009
  p = stpcpy (line, command);
866
1010
  for (i=0; i < argc; i++)
889
1033
                        run_command_status_cb, ctrl);
890
1034
  xfree (line);
891
1035
  log_info ("response of dirmngr: %s\n", rc? gpg_strerror (rc): "okay");
 
1036
  release_dirmngr (ctrl);
892
1037
  return rc;
893
1038
}