ksba_cert_t get_one_cert (const char *fname) { gpg_error_t err; FILE *fp; ksba_reader_t r; ksba_cert_t cert; fp = fopen (fname, "r"); if (!fp) { fprintf (stderr, "%s:%d: can't open `%s': %s\n", __FILE__, __LINE__, fname, strerror (errno)); exit (1); } err = ksba_reader_new (&r); if (err) fail_if_err (err); err = ksba_reader_set_file (r, fp); fail_if_err (err); err = ksba_cert_new (&cert); if (err) fail_if_err (err); err = ksba_cert_read_der (cert, r); fail_if_err2 (fname, err); return cert; }
/* Return the last found cert. Caller must free it. */ int keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert) { const unsigned char *buffer; size_t length; size_t cert_off, cert_len; ksba_reader_t reader = NULL; ksba_cert_t cert = NULL; int rc; if (!hd) return gpg_error (GPG_ERR_INV_VALUE); if (!hd->found.blob) return gpg_error (GPG_ERR_NOTHING_FOUND); if (blob_get_type (hd->found.blob) != BLOBTYPE_X509) return gpg_error (GPG_ERR_WRONG_BLOB_TYPE); buffer = _keybox_get_blob_image (hd->found.blob, &length); if (length < 40) return gpg_error (GPG_ERR_TOO_SHORT); cert_off = get32 (buffer+8); cert_len = get32 (buffer+12); if (cert_off+cert_len > length) return gpg_error (GPG_ERR_TOO_SHORT); rc = ksba_reader_new (&reader); if (rc) return rc; rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len); if (rc) { ksba_reader_release (reader); /* fixme: need to map the error codes */ return gpg_error (GPG_ERR_GENERAL); } rc = ksba_cert_new (&cert); if (rc) { ksba_reader_release (reader); return rc; } rc = ksba_cert_read_der (cert, reader); if (rc) { ksba_cert_release (cert); ksba_reader_release (reader); /* fixme: need to map the error codes */ return gpg_error (GPG_ERR_GENERAL); } *r_cert = cert; ksba_reader_release (reader); return 0; }
/* Load certificates from the directory DIRNAME. All certificates matching the pattern "*.crt" or "*.der" are loaded. We assume that certificates are DER encoded and not PEM encapsulated. The cache should be in a locked state when calling this function. */ static gpg_error_t load_certs_from_dir (const char *dirname, int are_trusted) { gpg_error_t err; DIR *dir; struct dirent *ep; char *p; size_t n; estream_t fp; ksba_reader_t reader; ksba_cert_t cert; char *fname = NULL; dir = opendir (dirname); if (!dir) { if (opt.system_daemon) log_info (_("can't access directory '%s': %s\n"), dirname, strerror (errno)); return 0; /* We do not consider this a severe error. */ } while ( (ep=readdir (dir)) ) { p = ep->d_name; if (*p == '.' || !*p) continue; /* Skip any hidden files and invalid entries. */ n = strlen (p); if ( n < 5 || (strcmp (p+n-4,".crt") && strcmp (p+n-4,".der"))) continue; /* Not the desired "*.crt" or "*.der" pattern. */ xfree (fname); fname = make_filename (dirname, p, NULL); fp = es_fopen (fname, "rb"); if (!fp) { log_error (_("can't open '%s': %s\n"), fname, strerror (errno)); continue; } err = create_estream_ksba_reader (&reader, fp); if (err) { es_fclose (fp); continue; } err = ksba_cert_new (&cert); if (!err) err = ksba_cert_read_der (cert, reader); ksba_reader_release (reader); es_fclose (fp); if (err) { log_error (_("can't parse certificate '%s': %s\n"), fname, gpg_strerror (err)); ksba_cert_release (cert); continue; } err = put_cert (cert, 1, are_trusted, NULL); if (gpg_err_code (err) == GPG_ERR_DUP_VALUE) log_info (_("certificate '%s' already cached\n"), fname); else if (!err) { if (are_trusted) log_info (_("trusted certificate '%s' loaded\n"), fname); else log_info (_("certificate '%s' loaded\n"), fname); if (opt.verbose) { 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); } } else log_error (_("error loading certificate '%s': %s\n"), fname, gpg_strerror (err)); ksba_cert_release (cert); } xfree (fname); closedir (dir); return 0; }
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; }
/* Return true if the key in BLOB matches the 20 bytes keygrip GRIP. We don't have the keygrips as meta data, thus we need to parse the certificate. Fixme: We might want to return proper error codes instead of failing a search for invalid certificates etc. */ static int blob_x509_has_grip (KEYBOXBLOB blob, const unsigned char *grip) { int rc; const unsigned char *buffer; size_t length; size_t cert_off, cert_len; ksba_reader_t reader = NULL; ksba_cert_t cert = NULL; ksba_sexp_t p = NULL; gcry_sexp_t s_pkey; unsigned char array[20]; unsigned char *rcp; size_t n; buffer = _keybox_get_blob_image (blob, &length); if (length < 40) return 0; /* Too short. */ cert_off = get32 (buffer+8); cert_len = get32 (buffer+12); if (cert_off+cert_len > length) return 0; /* Too short. */ rc = ksba_reader_new (&reader); if (rc) return 0; /* Problem with ksba. */ rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len); if (rc) goto failed; rc = ksba_cert_new (&cert); if (rc) goto failed; rc = ksba_cert_read_der (cert, reader); if (rc) goto failed; p = ksba_cert_get_public_key (cert); if (!p) goto failed; n = gcry_sexp_canon_len (p, 0, NULL, NULL); if (!n) goto failed; rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)p, n); if (rc) { gcry_sexp_release (s_pkey); goto failed; } rcp = gcry_pk_get_keygrip (s_pkey, array); gcry_sexp_release (s_pkey); if (!rcp) goto failed; /* Can't calculate keygrip. */ xfree (p); ksba_cert_release (cert); ksba_reader_release (reader); return !memcmp (array, grip, 20); failed: xfree (p); ksba_cert_release (cert); ksba_reader_release (reader); return 0; }
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; }
/* 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; }