New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hash API password and comparison #5715
Conversation
|
TODO:
|
|
Tested with openssl 1.0.1g-0.30.1 on sles 11.4. Thx @N-o-X |
|
Maybe we should make the |
|
I thought about this as well, but then we'd have to print the password out to console. Which would then make the workflow icinga2 api user ... > .../api_user.conf impossible |
d7016f3
to
f02ad93
Compare
|
Ready for review from my side tl;dr:
|
lib/cli/apisetuputility.cpp
Outdated
| String apiUsersPath = GetConfdPath() + "/api-users.conf"; | ||
| String api_username = "root"; // TODO make this available as cli parameter? | ||
| String api_password = RandomString(8); | ||
| String apiUsersPath = GetConfdPath() + "/api-users.conf"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Styleguide.
lib/cli/apisetuputility.cpp
Outdated
| @@ -169,7 +169,7 @@ bool ApiSetupUtility::SetupMasterApiUser(void) | |||
| << " * The APIUser objects are used for authentication against the API.\n" | |||
| << " */\n" | |||
| << "object ApiUser \"" << api_username << "\" {\n" | |||
| << " password = \"" << api_password << "\"\n" | |||
| << " password: \"" << api_password << "\"\n" | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will break the config.
lib/cli/apiusercommand.cpp
Outdated
|
|
||
| String ApiUserCommand::GetDescription(void) const | ||
| { | ||
| return "Create a hashed user + password string for the Icinga 2 API"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: Replace + with and.
lib/cli/apiusercommand.cpp
Outdated
|
|
||
| String user = vm["user"].as<std::string>(); | ||
| String passwd = vm["passwd"].as<std::string>(); | ||
| String salt = vm.count("salt") ? String(vm["salt"].as<std::string>()) : RandomString(8); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style.
lib/cli/apiusercommand.cpp
Outdated
| String passwd = vm["passwd"].as<std::string>(); | ||
| String salt = vm.count("salt") ? String(vm["salt"].as<std::string>()) : RandomString(8); | ||
|
|
||
| String hashed_passwd = ApiUser::CreateHashedPasswordString(passwd, salt, true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variable name should be hashedPassword. We will apply this through the entire code base soon.
lib/remote/apiuser.hpp
Outdated
| void SetPasswd(String s) { | ||
| m_Hashed_passwd = s; | ||
| } | ||
| #endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where's that block implemented/used?
lib/remote/apiuser.hpp
Outdated
| #endif | ||
| private: | ||
| String m_Salt; | ||
| String m_Hashed_passwd; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style.
lib/remote/httpserverconnection.cpp
Outdated
| if (password.IsEmpty()) | ||
| user.reset(); | ||
| else if (user && user->GetPassword() != password) | ||
| if (password.IsEmpty() || !user->ComparePassword(password)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will terminate with a SIGSEGV if user is not defined. The check should include if (user && ..) and was split for that reason before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't user.reset() fail as well if user not defined ?
test/remote-user.cpp
Outdated
|
|
||
| user->SetSalt("BBBP"); | ||
| BOOST_CHECK(!user->ComparePassword("icinga2icinga")); | ||
| #endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any specific reason not to run this in release builds?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The getter and setters for passwords are only available in a debug build. To prevent other modules from setting them in the future. I tried to solve this by using friend classes but failed dramatically.
So tests are still an open todo
lib/base/tlsutility.cpp
Outdated
| { | ||
| unsigned char digest[SHA256_DIGEST_LENGTH]; | ||
| PKCS5_PBKDF2_HMAC(password.CStr(), password.GetLength(), reinterpret_cast<const unsigned char *>(salt.CStr()), | ||
| salt.GetLength(), iterations, EVP_sha256(), SHA256_DIGEST_LENGTH, digest); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style, use 4 spaces for indent.
|
I've now understood its purpose, I feared that this would need a local storage (which it does not). The variable names should apply our coding style, similar to some other locations marked in the review. |
|
Additional idea by Gunnar:
|
f02ad93
to
bd27d67
Compare
|
Requesting re-review |
3174559
to
61c4ec0
Compare
--oneline can now be used to print out only the password hash string. This can be used to update ApiUser passwords through the API. There is also now a validation to make use salt does not contain a '$' which would break verification.
61c4ec0
to
2bd35aa
Compare
595690a
to
0a0795f
Compare
|
Refs CVE-2018-6535 |
|
This should be merged after #6103 to easier resolve merge conflicts |
|
I just stumbled across this PR, sorry for commenting on this long after it was merged.
This sounds like a good idea to me. Passing the password as a command line argument leaks it to other users on the system via the process list. IMHO there should be some alternative method like reading it from the console, using an environment variable, generating a random password, etc.
You could print the config snippet to stdout and the cleartext password to stderr. Then redirecting stdout to a file would still show the password in the terminal. |
|
@julianbrost Both are additions which can be added in a future version. Could you make a new issue for those? We want to release 2.8.2 as soon as possible. |
This change requires (afaik, TODO: test) openssl version 1.X to work. To my knowledge this is supported by even Sles 11, Solaris 10 and AIX.
The patch adds the option to save passwords as hashes, the new
api usercommand can create them, and hashes clear text passwords at startup.This should protect icinga2 against timing attacks and improperly secured config files. It is backwards compatible and should not break any other applications.
refs #4920