From ff06bfac111fe46f0b4453b19a7cfe2589644b87 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 12 Feb 2018 17:22:50 +0300 Subject: Use abbreviated to 16 chars SHA256 fingerprint as certificate id --- bpkg/auth.cxx | 62 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 23 deletions(-) (limited to 'bpkg/auth.cxx') diff --git a/bpkg/auth.cxx b/bpkg/auth.cxx index 06555e2..ebc98b0 100644 --- a/bpkg/auth.cxx +++ b/bpkg/auth.cxx @@ -113,10 +113,15 @@ namespace bpkg return cert; } - // Calculate the real repository certificate fingerprint. Return the compact - // form (no colons, lower case). + // Calculate the real repository certificate fingerprint. // - static string + struct fingerprint + { + string canonical; // Canonical representation. + string abbreviated; // No colons, lower case, first 16 chars only. + }; + + static fingerprint real_fingerprint (const common_options& co, const string& pem, const repository_location& rl) @@ -153,7 +158,11 @@ namespace bpkg if (os.wait () && s.size () > n && s.compare (0, n, "SHA256 Fingerprint=") == 0) - return fingerprint_to_sha256 (string (s, n)); + { + string fp (s, n); + string ab (fingerprint_to_sha256 (fp, 16)); + return {move (fp), move (ab)}; + } } catch (const invalid_argument&) { @@ -182,24 +191,26 @@ namespace bpkg throw failed (); } - // Calculate the repository certificate fingerprint. Return the compact form - // (no colons, lower case). + // Calculate the repository certificate fingerprint. For dummy certificate + // only the abbreviated form is meaningful (see certificate class definition + // for details). // - static string + static fingerprint cert_fingerprint (const common_options& co, const optional& pem, const repository_location& rl) { return pem ? real_fingerprint (co, *pem, rl) - : sha256 (name_prefix (rl)).string (); + : fingerprint {string (), + sha256 (name_prefix (rl)).abbreviated_string (16)}; } // Parse the PEM-encoded certificate representation. // static shared_ptr parse_cert (const common_options& co, - const string& fp, + const fingerprint& fp, const string& pem, const string& repo) { @@ -408,7 +419,8 @@ namespace bpkg shared_ptr cert ( make_shared ( - fp, + fp.abbreviated, + fp.canonical, move (name), move (org), move (email), @@ -472,7 +484,7 @@ namespace bpkg // static shared_ptr auth_real (const common_options& co, - const string& fp, + const fingerprint& fp, const string& pem, const repository_location& rl) { @@ -485,8 +497,6 @@ namespace bpkg verify_cert (*cert, rl); - string cert_fp (sha256_to_fingerprint (cert->fingerprint)); - // @@ Is there a way to intercept CLI parsing for the specific option of // the standard type to validate/convert the value? If there were, we could // validate the option value converting fp to sha (internal representation @@ -496,7 +506,7 @@ namespace bpkg // will probably be an overkill here. // bool trust (co.trust_yes () || - co.trust ().find (cert_fp) != co.trust ().end ()); + co.trust ().find (cert->fingerprint) != co.trust ().end ()); if (trust) { @@ -517,7 +527,7 @@ namespace bpkg << cert->organization << "\" <" << cert->email << ">"; text << "certificate SHA256 fingerprint:"; - text << cert_fp; + text << cert->fingerprint; } if (co.trust_no () || !yn_prompt ("trust this certificate? [y/n]")) @@ -539,8 +549,8 @@ namespace bpkg tracer trace ("auth_cert"); tracer_guard tg (db, trace); - string fp (cert_fingerprint (co, pem, rl)); - shared_ptr cert (db.find (fp)); + fingerprint fp (cert_fingerprint (co, pem, rl)); + shared_ptr cert (db.find (fp.abbreviated)); if (cert != nullptr) { @@ -549,14 +559,17 @@ namespace bpkg return cert; } - cert = pem ? auth_real (co, fp, *pem, rl) : auth_dummy (co, fp, rl); + cert = pem + ? auth_real (co, fp, *pem, rl) + : auth_dummy (co, fp.abbreviated, rl); + db.persist (cert); // Save the certificate file. // if (pem) { - path f (conf / certs_dir / path (fp + ".pem")); + path f (conf / certs_dir / path (cert->id + ".pem")); try { @@ -596,8 +609,10 @@ namespace bpkg // If we have no configuration, go straight to authenticating a new // certificate. // - string fp (cert_fingerprint (co, pem, rl)); - r = pem ? auth_real (co, fp, *pem, rl) : auth_dummy (co, fp, rl); + fingerprint fp (cert_fingerprint (co, pem, rl)); + r = pem + ? auth_real (co, fp, *pem, rl) + : auth_dummy (co, fp.abbreviated, rl); } else if (transaction::has_current ()) { @@ -660,7 +675,7 @@ namespace bpkg } else { - f = *conf / certs_dir / path (cert.fingerprint + ".pem"); + f = *conf / certs_dir / path (cert.id + ".pem"); } // Make sure the names are either equal or the certificate name is a @@ -835,7 +850,8 @@ namespace bpkg // No sense to calculate the fingerprint for the certificate being used // just to check the expiration date. // - shared_ptr cert (parse_cert (co, "", cert_pem, r)); + shared_ptr cert ( + parse_cert (co, fingerprint (), cert_pem, r)); timestamp now (system_clock::now ()); -- cgit v1.1