void * dump_proc(void * args) { struct dump_manager *manager = (struct dump_manager*) args; while (1) { wait_usb_plugin(manager); unmount_usb(manager); if (mount_usb(manager) == 0) { get_record_id(manager); change_led_mode(LED_DUMP); if (exe_update(manager) != 0) { get_config_info(manager); get_time(&(manager->time_export)); dump_status(manager); dump_serial(manager); dump_wave(manager); } unmount_usb(manager); change_led_mode(LED_DUMP_FINISHED); wait_usb_plugout(manager); change_led_mode(LED_NORMAL); } } return NULL; }
/* Log the certificate's name in "#SN/ISSUERDN" format along with TEXT. */ void cert_log_name (const char *text, ksba_cert_t cert) { log_info ("%s", text? text:"certificate" ); if (cert) { ksba_sexp_t sn; char *p; p = ksba_cert_get_issuer (cert, 0); sn = ksba_cert_get_serial (cert); if (p && sn) { log_printf (" #"); dump_serial (sn); log_printf ("/"); dump_string (p); } else log_printf (" [invalid]"); ksba_free (sn); xfree (p); } log_printf ("\n"); }
/* Given the certificate CERT locate the issuer for this certificate and return it at R_CERT. Returns 0 on success or GPG_ERR_NOT_FOUND. */ gpg_error_t find_issuing_cert (ctrl_t ctrl, ksba_cert_t cert, ksba_cert_t *r_cert) { gpg_error_t err; char *issuer_dn; ksba_cert_t issuer_cert = NULL; ksba_name_t authid; ksba_sexp_t authidno; ksba_sexp_t keyid; *r_cert = NULL; issuer_dn = ksba_cert_get_issuer (cert, 0); if (!issuer_dn) { log_error (_("no issuer found in certificate\n")); err = gpg_error (GPG_ERR_BAD_CERT); goto leave; } /* First we need to check whether we can return that certificate using the authorithyKeyIdentifier. */ err = ksba_cert_get_auth_key_id (cert, &keyid, &authid, &authidno); if (err) { log_info (_("error getting authorityKeyIdentifier: %s\n"), gpg_strerror (err)); } else { const char *s = ksba_name_enum (authid, 0); if (s && *authidno) { issuer_cert = find_cert_bysn (ctrl, s, authidno); } if (!issuer_cert && keyid) { /* Not found by issuer+s/n. Now that we have an AKI keyIdentifier look for a certificate with a matching SKI. */ issuer_cert = find_cert_bysubject (ctrl, issuer_dn, keyid); } /* Print a note so that the user does not feel too helpless when an issuer certificate was found and gpgsm prints BAD signature because it is not the correct one. */ if (!issuer_cert) { log_info ("issuer certificate "); if (keyid) { log_printf ("{"); dump_serial (keyid); log_printf ("} "); } if (authidno) { log_printf ("(#"); dump_serial (authidno); log_printf ("/"); dump_string (s); log_printf (") "); } log_printf ("not found using authorityKeyIdentifier\n"); } ksba_name_release (authid); xfree (authidno); xfree (keyid); } /* If this did not work, try just with the issuer's name and assume that there is only one such certificate. We only look into our cache then. */ if (err || !issuer_cert) { issuer_cert = get_cert_bysubject (issuer_dn, 0); if (issuer_cert) err = 0; } leave: if (!err && !issuer_cert) err = gpg_error (GPG_ERR_NOT_FOUND); xfree (issuer_dn); if (err) ksba_cert_release (issuer_cert); else *r_cert = issuer_cert; return err; }
/* Return the certificate matching ISSUER_DN and SERIALNO; if it is not already in the cache, try to find it from other resources. */ ksba_cert_t find_cert_bysn (ctrl_t ctrl, const char *issuer_dn, ksba_sexp_t serialno) { gpg_error_t err; ksba_cert_t cert; cert_fetch_context_t context = NULL; char *hexsn, *buf; /* First check whether it has already been cached. */ cert = get_cert_bysn (issuer_dn, serialno); if (cert) return cert; /* Ask back to the service requester to return the certificate. This is because we can assume that he already used the certificate while checking for the CRL. */ hexsn = serial_hex (serialno); if (!hexsn) { log_error ("serial_hex() failed\n"); return NULL; } buf = xtrymalloc (1 + strlen (hexsn) + 1 + strlen (issuer_dn) + 1); if (!buf) { log_error ("can't allocate enough memory: %s\n", strerror (errno)); xfree (hexsn); return NULL; } strcpy (stpcpy (stpcpy (stpcpy (buf, "#"), hexsn),"/"), issuer_dn); xfree (hexsn); cert = get_cert_local (ctrl, buf); xfree (buf); if (cert) { cache_cert (cert); return cert; /* Done. */ } if (DBG_LOOKUP) log_debug ("find_cert_bysn: certificate not returned by caller" " - doing lookup\n"); /* Retrieve the certificate from external resources. */ while (!cert) { ksba_sexp_t sn; char *issdn; if (!context) { err = ca_cert_fetch (ctrl, &context, issuer_dn); if (err) { log_error (_("error fetching certificate by S/N: %s\n"), gpg_strerror (err)); break; } } err = fetch_next_ksba_cert (context, &cert); if (err) { log_error (_("error fetching certificate by S/N: %s\n"), gpg_strerror (err) ); break; } issdn = ksba_cert_get_issuer (cert, 0); if (strcmp (issuer_dn, issdn)) { log_debug ("find_cert_bysn: Ooops: issuer DN does not match\n"); ksba_cert_release (cert); cert = NULL; ksba_free (issdn); break; } sn = ksba_cert_get_serial (cert); if (DBG_LOOKUP) { log_debug (" considering certificate (#"); dump_serial (sn); log_printf ("/"); dump_string (issdn); log_printf (")\n"); } if (!compare_serialno (serialno, sn)) { ksba_free (sn); ksba_free (issdn); cache_cert (cert); if (DBG_LOOKUP) log_debug (" found\n"); break; /* Ready. */ } ksba_free (sn); ksba_free (issdn); ksba_cert_release (cert); cert = NULL; } end_cert_fetch (context); return cert; }
/* Check the signature of an OCSP repsonse. OCSP is the context, S_SIG the signature value and MD the handle of the hash we used for the response. This function automagically finds the correct public key. If SIGNER_FPR_LIST is not NULL, the default OCSP reponder has been used and thus the certificate is one of those identified by the fingerprints. */ static gpg_error_t check_signature (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_sexp_t s_sig, gcry_md_hd_t md, fingerprint_list_t signer_fpr_list) { gpg_error_t err; int algo, cert_idx; gcry_sexp_t s_hash; ksba_cert_t cert; /* Create a suitable S-expression with the hash value of our response. */ gcry_md_final (md); algo = gcry_md_get_algo (md); if (algo != GCRY_MD_SHA1 ) { log_error (_("only SHA-1 is supported for OCSP responses\n")); return gpg_error (GPG_ERR_DIGEST_ALGO); } err = gcry_sexp_build (&s_hash, NULL, "(data(flags pkcs1)(hash sha1 %b))", gcry_md_get_algo_dlen (algo), gcry_md_read (md, algo)); if (err) { log_error (_("creating S-expression failed: %s\n"), gcry_strerror (err)); return err; } /* Get rid of old OCSP specific certificate references. */ release_ctrl_ocsp_certs (ctrl); if (signer_fpr_list && !signer_fpr_list->next) { /* There is exactly one signer fingerprint given. Thus we use the default OCSP responder's certificate and instantly know the certificate to use. */ cert = get_cert_byhexfpr (signer_fpr_list->hexfpr); if (!cert) cert = get_cert_local (ctrl, signer_fpr_list->hexfpr); if (cert) { err = check_signature_core (ctrl, cert, s_sig, s_hash, signer_fpr_list); ksba_cert_release (cert); cert = NULL; if (!err) { gcry_sexp_release (s_hash); return 0; /* Successfully verified the signature. */ } } } else { char *name; ksba_sexp_t keyid; /* Put all certificates included in the response into the cache and setup a list of those certificate which will later be preferred used when locating certificates. */ for (cert_idx=0; (cert = ksba_ocsp_get_cert (ocsp, cert_idx)); cert_idx++) { cert_ref_t cref; cref = xtrymalloc (sizeof *cref); if (!cref) log_error (_("allocating list item failed: %s\n"), gcry_strerror (err)); else if (!cache_cert_silent (cert, &cref->fpr)) { cref->next = ctrl->ocsp_certs; ctrl->ocsp_certs = cref; } else xfree (cref); } /* Get the certificate by means of the responder ID. */ err = ksba_ocsp_get_responder_id (ocsp, &name, &keyid); if (err) { log_error (_("error getting responder ID: %s\n"), gcry_strerror (err)); return err; } cert = find_cert_bysubject (ctrl, name, keyid); if (!cert) { log_error ("responder certificate "); if (name) log_printf ("'/%s' ", name); if (keyid) { log_printf ("{"); dump_serial (keyid); log_printf ("} "); } log_printf ("not found\n"); } ksba_free (name); ksba_free (keyid); if (cert) { err = check_signature_core (ctrl, cert, s_sig, s_hash, signer_fpr_list); ksba_cert_release (cert); if (!err) { gcry_sexp_release (s_hash); return 0; /* Successfully verified the signature. */ } } } gcry_sexp_release (s_hash); log_error (_("no suitable certificate found to verify the OCSP response\n")); return gpg_error (GPG_ERR_NO_PUBKEY); }