diff options
author | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-02-16 18:06:24 +0300 |
---|---|---|
committer | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-02-16 18:06:24 +0300 |
commit | 04e26cfb286cbc71346a217021012bd82077c66f (patch) | |
tree | 82ac6c518620f66fabbafe9ea6aa51f398ecef13 | |
parent | 94e0d1dcb0474eb63e528acc76a3be90dc43163b (diff) | |
download | ydb-04e26cfb286cbc71346a217021012bd82077c66f.tar.gz |
intermediate changes
ref:4a4d54c4c155707e6ff62c98153351075e49f4a8
-rw-r--r-- | contrib/libs/jwt-cpp/README.md | 17 | ||||
-rw-r--r-- | contrib/libs/jwt-cpp/jwt.h | 136 | ||||
-rw-r--r-- | contrib/libs/jwt-cpp/ya.make | 20 | ||||
-rw-r--r-- | contrib/python/ya.make | 2 |
4 files changed, 115 insertions, 60 deletions
diff --git a/contrib/libs/jwt-cpp/README.md b/contrib/libs/jwt-cpp/README.md index 5dcdd10c51..5fc1459412 100644 --- a/contrib/libs/jwt-cpp/README.md +++ b/contrib/libs/jwt-cpp/README.md @@ -54,12 +54,23 @@ auto token = jwt::create() .sign(jwt::algorithm::hs256{"secret"}); ``` +Here is a simple example of creating a token that will expire in one hour: + +```c++ +auto token = jwt::create() + .set_issuer("auth0") + .set_issued_at(std::chrono::system_clock::now()) + .set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{3600}) + .sign(jwt::algorithm::hs256{"secret"}); +``` + ## Contributing If you have an improvement or found a bug feel free to [open an issue](https://github.com/Thalhammer/jwt-cpp/issues/new) or add the change and create a pull request. If you file a bug please make sure to include as much information about your environment (compiler version, etc.) as possible to help reproduce the issue. If you add a new feature please make sure to also include test cases for it. ## Dependencies In order to use jwt-cpp you need the following tools. * libcrypto (openssl or compatible) +* libssl-dev (for the header files) * a compiler supporting at least c++11 * basic stl support @@ -68,9 +79,15 @@ In order to build the test cases you also need * pthread ## Troubleshooting +#### Expired tokens +If you are generating tokens that seem to immediately expire, you are likely not using UTC. Specifically, +if you use `get_time` to get the current time, it likely uses localtime, while this library uses UTC, +which may be why your token is immediately expiring. Please see example above on the right way to use current time. + #### Missing _HMAC amd _EVP_sha256 symbols on Mac There seems to exists a problem with the included openssl library of MacOS. Make sure you link to one provided by brew. See [here](https://github.com/Thalhammer/jwt-cpp/issues/6) for more details. + #### Building on windows fails with syntax errors The header "Windows.h", which is often included in windowsprojects, defines macros for MIN and MAX which screw up std::numeric_limits. See [here](https://github.com/Thalhammer/jwt-cpp/issues/5) for more details. To fix this do one of the following things: diff --git a/contrib/libs/jwt-cpp/jwt.h b/contrib/libs/jwt-cpp/jwt.h index a8c94c0c65..129554699a 100644 --- a/contrib/libs/jwt-cpp/jwt.h +++ b/contrib/libs/jwt-cpp/jwt.h @@ -71,6 +71,59 @@ namespace jwt { {} }; + namespace helper { + inline + std::string extract_pubkey_from_cert(const std::string& certstr, const std::string& pw = "") { + // TODO: Cannot find the exact version this change happended +#if OPENSSL_VERSION_NUMBER <= 0x1000114fL + std::unique_ptr<BIO, decltype(&BIO_free_all)> certbio(BIO_new_mem_buf(const_cast<char*>(certstr.data()), certstr.size()), BIO_free_all); +#else + std::unique_ptr<BIO, decltype(&BIO_free_all)> certbio(BIO_new_mem_buf(certstr.data(), certstr.size()), BIO_free_all); +#endif + std::unique_ptr<BIO, decltype(&BIO_free_all)> keybio(BIO_new(BIO_s_mem()), BIO_free_all); + + std::unique_ptr<X509, decltype(&X509_free)> cert(PEM_read_bio_X509(certbio.get(), nullptr, nullptr, const_cast<char*>(pw.c_str())), X509_free); + if (!cert) throw rsa_exception("Error loading cert into memory"); + std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> key(X509_get_pubkey(cert.get()), EVP_PKEY_free); + if(!key) throw rsa_exception("Error getting public key from certificate"); + if(!PEM_write_bio_PUBKEY(keybio.get(), key.get())) throw rsa_exception("Error writing public key data in PEM format"); + char* ptr = nullptr; + auto len = BIO_get_mem_data(keybio.get(), &ptr); + if(len <= 0 || ptr == nullptr) throw rsa_exception("Failed to convert pubkey to pem"); + std::string res(ptr, len); + return res; + } + + inline + std::shared_ptr<EVP_PKEY> load_public_key_from_string(const std::string& key, const std::string& password = "") { + std::unique_ptr<BIO, decltype(&BIO_free_all)> pubkey_bio(BIO_new(BIO_s_mem()), BIO_free_all); + if(key.substr(0, 27) == "-----BEGIN CERTIFICATE-----") { + auto epkey = helper::extract_pubkey_from_cert(key, password); + if ((size_t)BIO_write(pubkey_bio.get(), epkey.data(), epkey.size()) != epkey.size()) + throw rsa_exception("failed to load public key: bio_write failed"); + } else { + if ((size_t)BIO_write(pubkey_bio.get(), key.data(), key.size()) != key.size()) + throw rsa_exception("failed to load public key: bio_write failed"); + } + + std::shared_ptr<EVP_PKEY> pkey(PEM_read_bio_PUBKEY(pubkey_bio.get(), nullptr, nullptr, (void*)password.c_str()), EVP_PKEY_free); + if (!pkey) + throw rsa_exception("failed to load public key: PEM_read_bio_PUBKEY failed"); + return pkey; + } + + inline + std::shared_ptr<EVP_PKEY> load_private_key_from_string(const std::string& key, const std::string& password = "") { + std::unique_ptr<BIO, decltype(&BIO_free_all)> privkey_bio(BIO_new(BIO_s_mem()), BIO_free_all); + if ((size_t)BIO_write(privkey_bio.get(), key.data(), key.size()) != key.size()) + throw rsa_exception("failed to load private key: bio_write failed"); + std::shared_ptr<EVP_PKEY> pkey(PEM_read_bio_PrivateKey(privkey_bio.get(), nullptr, nullptr, const_cast<char*>(password.c_str())), EVP_PKEY_free); + if (!pkey) + throw rsa_exception("failed to load private key: PEM_read_bio_PrivateKey failed"); + return pkey; + } + } + namespace algorithm { /** * "none" algorithm. @@ -173,25 +226,12 @@ namespace jwt { rsa(const std::string& public_key, const std::string& private_key, const std::string& public_key_password, const std::string& private_key_password, const EVP_MD*(*md)(), const std::string& name) : md(md), alg_name(name) { - std::unique_ptr<BIO, decltype(&BIO_free_all)> pubkey_bio(BIO_new(BIO_s_mem()), BIO_free_all); - if ((size_t)BIO_write(pubkey_bio.get(), public_key.data(), public_key.size()) != public_key.size()) - throw rsa_exception("failed to load public key: bio_write failed"); - pkey.reset(PEM_read_bio_PUBKEY(pubkey_bio.get(), nullptr, nullptr, (void*)public_key_password.c_str()), EVP_PKEY_free); - if (!pkey) - throw rsa_exception("failed to load public key: PEM_read_bio_PUBKEY failed"); - if (!private_key.empty()) { - std::unique_ptr<BIO, decltype(&BIO_free_all)> privkey_bio(BIO_new(BIO_s_mem()), BIO_free_all); - if ((size_t)BIO_write(privkey_bio.get(), private_key.data(), private_key.size()) != private_key.size()) - throw rsa_exception("failed to load private key: bio_write failed"); - RSA* privkey = PEM_read_bio_RSAPrivateKey(privkey_bio.get(), nullptr, nullptr, (void*)private_key_password.c_str()); - if (privkey == nullptr) - throw rsa_exception("failed to load private key: PEM_read_bio_RSAPrivateKey failed"); - if (EVP_PKEY_assign_RSA(pkey.get(), privkey) == 0) { - RSA_free(privkey); - throw rsa_exception("failed to load private key: EVP_PKEY_assign_RSA failed"); - } - } + pkey = helper::load_private_key_from_string(private_key, private_key_password); + } else if(!public_key.empty()) { + pkey = helper::load_public_key_from_string(public_key, public_key_password); + } else + throw rsa_exception("at least one of public or private key need to be present"); } /** * Sign jwt data @@ -240,8 +280,9 @@ namespace jwt { throw signature_verification_exception("failed to verify signature: VerifyInit failed"); if (!EVP_VerifyUpdate(ctx.get(), data.data(), data.size())) throw signature_verification_exception("failed to verify signature: VerifyUpdate failed"); - if (!EVP_VerifyFinal(ctx.get(), (const unsigned char*)signature.data(), signature.size(), pkey.get())) - throw signature_verification_exception(); + auto res = EVP_VerifyFinal(ctx.get(), (const unsigned char*)signature.data(), signature.size(), pkey.get()); + if (res != 1) + throw signature_verification_exception("evp verify final failed: " + std::to_string(res) + " " + ERR_error_string(ERR_get_error(), NULL)); } /** * Returns the algorithm name provided to the constructor @@ -274,22 +315,32 @@ namespace jwt { ecdsa(const std::string& public_key, const std::string& private_key, const std::string& public_key_password, const std::string& private_key_password, const EVP_MD*(*md)(), const std::string& name) : md(md), alg_name(name) { - if (private_key.empty()) { + if (!public_key.empty()) { std::unique_ptr<BIO, decltype(&BIO_free_all)> pubkey_bio(BIO_new(BIO_s_mem()), BIO_free_all); - if ((size_t)BIO_write(pubkey_bio.get(), public_key.data(), public_key.size()) != public_key.size()) - throw ecdsa_exception("failed to load public key: bio_write failed"); + if(public_key.substr(0, 27) == "-----BEGIN CERTIFICATE-----") { + auto epkey = helper::extract_pubkey_from_cert(public_key, public_key_password); + if ((size_t)BIO_write(pubkey_bio.get(), epkey.data(), epkey.size()) != epkey.size()) + throw ecdsa_exception("failed to load public key: bio_write failed"); + } else { + if ((size_t)BIO_write(pubkey_bio.get(), public_key.data(), public_key.size()) != public_key.size()) + throw ecdsa_exception("failed to load public key: bio_write failed"); + } pkey.reset(PEM_read_bio_EC_PUBKEY(pubkey_bio.get(), nullptr, nullptr, (void*)public_key_password.c_str()), EC_KEY_free); if (!pkey) throw ecdsa_exception("failed to load public key: PEM_read_bio_EC_PUBKEY failed"); - } else { + } + + if (!private_key.empty()) { std::unique_ptr<BIO, decltype(&BIO_free_all)> privkey_bio(BIO_new(BIO_s_mem()), BIO_free_all); if ((size_t)BIO_write(privkey_bio.get(), private_key.data(), private_key.size()) != private_key.size()) - throw ecdsa_exception("failed to load private key: bio_write failed"); - pkey.reset(PEM_read_bio_ECPrivateKey(privkey_bio.get(), nullptr, nullptr, (void*)private_key_password.c_str()), EC_KEY_free); + throw rsa_exception("failed to load private key: bio_write failed"); + pkey.reset(PEM_read_bio_ECPrivateKey(privkey_bio.get(), nullptr, nullptr, const_cast<char*>(private_key_password.c_str())), EC_KEY_free); if (!pkey) - throw ecdsa_exception("failed to load private key: PEM_read_bio_RSAPrivateKey failed"); + throw rsa_exception("failed to load private key: PEM_read_bio_ECPrivateKey failed"); } + if(!pkey) + throw rsa_exception("at least one of public or private key need to be present"); if(EC_KEY_check_key(pkey.get()) == 0) throw ecdsa_exception("failed to load key: key is invalid"); @@ -432,25 +483,12 @@ namespace jwt { pss(const std::string& public_key, const std::string& private_key, const std::string& public_key_password, const std::string& private_key_password, const EVP_MD*(*md)(), const std::string& name) : md(md), alg_name(name) { - std::unique_ptr<BIO, decltype(&BIO_free_all)> pubkey_bio(BIO_new(BIO_s_mem()), BIO_free_all); - if ((size_t)BIO_write(pubkey_bio.get(), public_key.data(), public_key.size()) != public_key.size()) - throw rsa_exception("failed to load public key: bio_write failed"); - pkey.reset(PEM_read_bio_PUBKEY(pubkey_bio.get(), nullptr, nullptr, (void*)public_key_password.c_str()), EVP_PKEY_free); - if (!pkey) - throw rsa_exception("failed to load public key: PEM_read_bio_PUBKEY failed"); - if (!private_key.empty()) { - std::unique_ptr<BIO, decltype(&BIO_free_all)> privkey_bio(BIO_new(BIO_s_mem()), BIO_free_all); - if ((size_t)BIO_write(privkey_bio.get(), private_key.data(), private_key.size()) != private_key.size()) - throw rsa_exception("failed to load private key: bio_write failed"); - RSA* privkey = PEM_read_bio_RSAPrivateKey(privkey_bio.get(), nullptr, nullptr, (void*)private_key_password.c_str()); - if (privkey == nullptr) - throw rsa_exception("failed to load private key: PEM_read_bio_RSAPrivateKey failed"); - if (EVP_PKEY_assign_RSA(pkey.get(), privkey) == 0) { - RSA_free(privkey); - throw rsa_exception("failed to load private key: EVP_PKEY_assign_RSA failed"); - } - } + pkey = helper::load_private_key_from_string(private_key, private_key_password); + } else if(!public_key.empty()) { + pkey = helper::load_public_key_from_string(public_key, public_key_password); + } else + throw rsa_exception("at least one of public or private key need to be present"); } /** * Sign jwt data @@ -1092,21 +1130,21 @@ namespace jwt { switch (str.size() % 4) { case 1: str += alphabet::base64url::fill(); -#ifdef __cpp_attributes +#ifdef __has_cpp_attribute #if __has_cpp_attribute(fallthrough) [[fallthrough]]; #endif #endif case 2: str += alphabet::base64url::fill(); -#ifdef __cpp_attributes +#ifdef __has_cpp_attribute #if __has_cpp_attribute(fallthrough) [[fallthrough]]; #endif #endif case 3: str += alphabet::base64url::fill(); -#ifdef __cpp_attributes +#ifdef __has_cpp_attribute #if __has_cpp_attribute(fallthrough) [[fallthrough]]; #endif @@ -1315,7 +1353,7 @@ namespace jwt { template<typename Clock> class verifier { struct algo_base { - virtual ~algo_base() = default; + virtual ~algo_base() {} virtual void verify(const std::string& data, const std::string& sig) = 0; }; template<typename T> diff --git a/contrib/libs/jwt-cpp/ya.make b/contrib/libs/jwt-cpp/ya.make index c7ddd33162..edf1ee6f9e 100644 --- a/contrib/libs/jwt-cpp/ya.make +++ b/contrib/libs/jwt-cpp/ya.make @@ -1,16 +1,7 @@ -# Generated by devtools/yamaker from nixpkgs 04d5f1e3a87d413181af5d6dd68568228addf1c3. +# Generated by devtools/yamaker from nixpkgs 21.11. LIBRARY() -OWNER( - pbludov - g:cpp-contrib -) - -VERSION(0.2.0) - -ORIGINAL_SOURCE(https://github.com/Thalhammer/jwt-cpp/archive/2b3ddae668f5b0dac92f57207312dc50b5bdb2f8.tar.gz) - LICENSE( BSD-2-Clause AND MIT @@ -18,6 +9,15 @@ LICENSE( LICENSE_TEXTS(.yandex_meta/licenses.list.txt) +OWNER( + pbludov + g:cpp-contrib +) + +VERSION(0.3.1) + +ORIGINAL_SOURCE(https://github.com/Thalhammer/jwt-cpp/archive/v0.3.1.tar.gz) + PEERDIR( contrib/libs/openssl ) diff --git a/contrib/python/ya.make b/contrib/python/ya.make index 7eee9ed4b0..37f5e24da8 100644 --- a/contrib/python/ya.make +++ b/contrib/python/ya.make @@ -914,6 +914,7 @@ RECURSE( python-rapidjson python-saml python-slugify + python-snappy python-socks python-telegram-bot python-utils @@ -1008,7 +1009,6 @@ RECURSE( slackclient smart-open smmap - snappy sniffio snowballstemmer sobol-seq |