static int import_one (ctrl_t ctrl, struct stats_s *stats, int in_fd) { int rc; Base64Context b64reader = NULL; ksba_reader_t reader; ksba_cert_t cert = NULL; ksba_cms_t cms = NULL; estream_t fp = NULL; ksba_content_type_t ct; int any = 0; fp = es_fdopen_nc (in_fd, "rb"); if (!fp) { rc = gpg_error_from_syserror (); log_error ("fdopen() failed: %s\n", strerror (errno)); goto leave; } rc = gpgsm_create_reader (&b64reader, ctrl, fp, 1, &reader); if (rc) { log_error ("can't create reader: %s\n", gpg_strerror (rc)); goto leave; } /* We need to loop here to handle multiple PEM objects in one file. */ do { ksba_cms_release (cms); cms = NULL; ksba_cert_release (cert); cert = NULL; ct = ksba_cms_identify (reader); if (ct == KSBA_CT_SIGNED_DATA) { /* This is probably a signed-only message - import the certs */ ksba_stop_reason_t stopreason; int i; rc = ksba_cms_new (&cms); if (rc) goto leave; rc = ksba_cms_set_reader_writer (cms, reader, NULL); if (rc) { log_error ("ksba_cms_set_reader_writer failed: %s\n", gpg_strerror (rc)); goto leave; } do { rc = ksba_cms_parse (cms, &stopreason); if (rc) { log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc)); goto leave; } if (stopreason == KSBA_SR_BEGIN_DATA) log_info ("not a certs-only message\n"); } while (stopreason != KSBA_SR_READY); for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++) { check_and_store (ctrl, stats, cert, 0); ksba_cert_release (cert); cert = NULL; } if (!i) log_error ("no certificate found\n"); else any = 1; } else if (ct == KSBA_CT_PKCS12) { /* This seems to be a pkcs12 message. */ rc = parse_p12 (ctrl, reader, stats); if (!rc) any = 1; } else if (ct == KSBA_CT_NONE) { /* Failed to identify this message - assume a certificate */ rc = ksba_cert_new (&cert); if (rc) goto leave; rc = ksba_cert_read_der (cert, reader); if (rc) goto leave; check_and_store (ctrl, stats, cert, 0); any = 1; } else { log_error ("can't extract certificates from input\n"); rc = gpg_error (GPG_ERR_NO_DATA); } ksba_reader_clear (reader, NULL, NULL); } while (!gpgsm_reader_eof_seen (b64reader)); leave: if (any && gpg_err_code (rc) == GPG_ERR_EOF) rc = 0; ksba_cms_release (cms); ksba_cert_release (cert); gpgsm_destroy_reader (b64reader); es_fclose (fp); return rc; }
static int import_one (ctrl_t ctrl, struct stats_s *stats, int in_fd) { int rc; Base64Context b64reader = NULL; ksba_reader_t reader; ksba_cert_t cert = NULL; ksba_cms_t cms = NULL; FILE *fp = NULL; ksba_content_type_t ct; int any = 0; fp = fdopen ( dup (in_fd), "rb"); if (!fp) { rc = gpg_error (gpg_err_code_from_errno (errno)); log_error ("fdopen() failed: %s\n", strerror (errno)); goto leave; } rc = gpgsm_create_reader (&b64reader, ctrl, fp, 1, &reader); if (rc) { log_error ("can't create reader: %s\n", gpg_strerror (rc)); goto leave; } /* We need to loop here to handle multiple PEM objects in one file. */ do { ksba_cms_release (cms); cms = NULL; ksba_cert_release (cert); cert = NULL; ct = ksba_cms_identify (reader); if (ct == KSBA_CT_SIGNED_DATA) { /* This is probably a signed-only message - import the certs */ ksba_stop_reason_t stopreason; int i; rc = ksba_cms_new (&cms); if (rc) goto leave; rc = ksba_cms_set_reader_writer (cms, reader, NULL); if (rc) { log_error ("ksba_cms_set_reader_writer failed: %s\n", gpg_strerror (rc)); goto leave; } do { rc = ksba_cms_parse (cms, &stopreason); if (rc) { log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc)); goto leave; } if (stopreason == KSBA_SR_BEGIN_DATA) log_info ("not a certs-only message\n"); } while (stopreason != KSBA_SR_READY); for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++) { check_and_store (ctrl, stats, cert, 0); ksba_cert_release (cert); cert = NULL; } if (!i) log_error ("no certificate found\n"); else any = 1; } else if (ct == KSBA_CT_PKCS12) { /* This seems to be a pkcs12 message. We use an external tool to parse the message and to store the private keys. We need to use a another reader here to parse the certificate we included in the p12 file; then we continue to look for other pkcs12 files (works only if they are in PEM format. */ FILE *certfp; Base64Context b64p12rdr; ksba_reader_t p12rdr; rc = parse_p12 (ctrl, reader, &certfp, stats); if (!rc) { any = 1; rewind (certfp); rc = gpgsm_create_reader (&b64p12rdr, ctrl, certfp, 1, &p12rdr); if (rc) { log_error ("can't create reader: %s\n", gpg_strerror (rc)); fclose (certfp); goto leave; } do { ksba_cert_release (cert); cert = NULL; rc = ksba_cert_new (&cert); if (!rc) { rc = ksba_cert_read_der (cert, p12rdr); if (!rc) check_and_store (ctrl, stats, cert, 0); } ksba_reader_clear (p12rdr, NULL, NULL); } while (!rc && !gpgsm_reader_eof_seen (b64p12rdr)); if (gpg_err_code (rc) == GPG_ERR_EOF) rc = 0; gpgsm_destroy_reader (b64p12rdr); fclose (certfp); if (rc) goto leave; } } else if (ct == KSBA_CT_NONE) { /* Failed to identify this message - assume a certificate */ rc = ksba_cert_new (&cert); if (rc) goto leave; rc = ksba_cert_read_der (cert, reader); if (rc) goto leave; check_and_store (ctrl, stats, cert, 0); any = 1; } else { log_error ("can't extract certificates from input\n"); rc = gpg_error (GPG_ERR_NO_DATA); } ksba_reader_clear (reader, NULL, NULL); } while (!gpgsm_reader_eof_seen (b64reader)); leave: if (any && gpg_err_code (rc) == GPG_ERR_EOF) rc = 0; ksba_cms_release (cms); ksba_cert_release (cert); gpgsm_destroy_reader (b64reader); if (fp) fclose (fp); return rc; }
/* Load certificates from FILE. The certificates are expected to be * PEM encoded so that it is possible to load several certificates. * TRUSTCLASSES is used to mark the certificates as trusted. The * cache should be in a locked state when calling this function. * NO_ERROR repalces an error message when FNAME was not found by an * information message. */ static gpg_error_t load_certs_from_file (const char *fname, unsigned int trustclasses, int no_error) { gpg_error_t err; estream_t fp = NULL; gnupg_ksba_io_t ioctx = NULL; ksba_reader_t reader; ksba_cert_t cert = NULL; fp = es_fopen (fname, "rb"); if (!fp) { err = gpg_error_from_syserror (); if (gpg_err_code (err) == GPG_ERR_ENONET && no_error) log_info (_("can't open '%s': %s\n"), fname, gpg_strerror (err)); else log_error (_("can't open '%s': %s\n"), fname, gpg_strerror (err)); goto leave; } err = gnupg_ksba_create_reader (&ioctx, (GNUPG_KSBA_IO_AUTODETECT | GNUPG_KSBA_IO_MULTIPEM), fp, &reader); if (err) { log_error ("can't create reader: %s\n", gpg_strerror (err)); goto leave; } /* Loop to read all certificates from the file. */ do { ksba_cert_release (cert); cert = NULL; err = ksba_cert_new (&cert); if (!err) err = ksba_cert_read_der (cert, reader); if (err) { if (gpg_err_code (err) == GPG_ERR_EOF) err = 0; else log_error (_("can't parse certificate '%s': %s\n"), fname, gpg_strerror (err)); goto leave; } err = put_cert (cert, 1, trustclasses, NULL); if (gpg_err_code (err) == GPG_ERR_DUP_VALUE) log_info (_("certificate '%s' already cached\n"), fname); else if (err) log_error (_("error loading certificate '%s': %s\n"), fname, gpg_strerror (err)); else if (opt.verbose > 1) { char *p; log_info (_("trusted certificate '%s' loaded\n"), fname); p = get_fingerprint_hexstring_colon (cert); log_info (_(" SHA1 fingerprint = %s\n"), p); xfree (p); cert_log_name (_(" issuer ="), cert); cert_log_subject (_(" subject ="), cert); } ksba_reader_clear (reader, NULL, NULL); } while (!gnupg_ksba_reader_eof_seen (ioctx)); leave: ksba_cert_release (cert); gnupg_ksba_destroy_reader (ioctx); es_fclose (fp); return err; }