diff options
author | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2019-10-19 01:43:15 -0500 |
---|---|---|
committer | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2019-10-19 01:43:15 -0500 |
commit | d3489c52d4ad1e5b17ce88e8b0e5142b30bb324e (patch) | |
tree | f724d77518fc09b0707311b31857e784abda6daa | |
parent | 2374778a55f9380ee5b821eb9563e20aad1bc3de (diff) | |
download | horizon-d3489c52d4ad1e5b17ce88e8b0e5142b30bb324e.tar.gz horizon-d3489c52d4ad1e5b17ce88e8b0e5142b30bb324e.tar.bz2 horizon-d3489c52d4ad1e5b17ce88e8b0e5142b30bb324e.tar.xz horizon-d3489c52d4ad1e5b17ce88e8b0e5142b30bb324e.zip |
hscript: Implement UserPassphrase, add tests
-rw-r--r-- | hscript/script.cc | 9 | ||||
-rw-r--r-- | hscript/user.cc | 43 | ||||
-rw-r--r-- | tests/fixtures/0091-userpw-basic.installfile | 7 | ||||
-rw-r--r-- | tests/fixtures/0092-userpw-without-pw.installfile | 7 | ||||
-rw-r--r-- | tests/fixtures/0093-userpw-unknown-name.installfile | 8 | ||||
-rw-r--r-- | tests/fixtures/0094-userpw-duplicate.installfile | 9 | ||||
-rw-r--r-- | tests/fixtures/0095-userpw-plaintext.installfile | 7 | ||||
-rw-r--r-- | tests/fixtures/0096-userpw-md5.installfile | 7 | ||||
-rw-r--r-- | tests/fixtures/0097-userpw-missing.installfile | 6 | ||||
-rw-r--r-- | tests/spec/validator.rb | 44 |
10 files changed, 141 insertions, 6 deletions
diff --git a/hscript/script.cc b/hscript/script.cc index dd5e931..8dbf9e1 100644 --- a/hscript/script.cc +++ b/hscript/script.cc @@ -567,6 +567,15 @@ bool Script::validate() const { failures++; } + /* REQ: Runner.Validate.userpw.None */ + if(!detail->passphrase) { + int line = detail->name->lineno(); + output_warning("installfile:" + std::to_string(line), + "username: " + acct.first + + " has no set passphrase", + "This account will not be able to log in."); + } + /* REQ: Runner.Validate.usericon */ if(detail->icon && !detail->icon->validate(this->opts)) { failures++; diff --git a/hscript/user.cc b/hscript/user.cc index 9bc6864..6081f55 100644 --- a/hscript/user.cc +++ b/hscript/user.cc @@ -100,14 +100,28 @@ static bool is_valid_name (const char *name) /* End above copyright ^ */ +/*! Determine if a string is a valid crypt passphrase + * @param pw The string to test for validity. + * @param key The name of key being validated ('rootpw', 'userpw', ...) + * @param lineno The line number where the key occurs. + * @returns true if +pw+ is a valid crypt passphrase; false otherwise. + */ +static bool string_is_crypt(const std::string &pw, const std::string &key, + int lineno) { + if(pw.size() < 5 || pw[0] != '$' || (pw[1] != '2' && pw[1] != '6') + || pw[2] != '$') { + output_error("installfile:" + std::to_string(lineno), + key + ": value is not a crypt-style encrypted passphrase"); + return false; + } + return true; +} + Key *RootPassphrase::parseFromData(const std::string &data, int lineno, int *errors, int *warnings) { - if(data.size() < 5 || data[0] != '$' || (data[1] != '2' && data[1] != '6') - || data[2] != '$') { + if(!string_is_crypt(data, "rootpw", lineno)) { if(errors) *errors += 1; - output_error("installfile:" + std::to_string(lineno), - "rootpw: value is not a crypt-style encrypted passphrase"); return nullptr; } return new RootPassphrase(lineno, data); @@ -219,11 +233,28 @@ bool UserAlias::execute(ScriptOptions) const { Key *UserPassphrase::parseFromData(const std::string &data, int lineno, int *errors, int *warnings) { - return nullptr; + /* REQ: Runner.Validate.userpw.Validity */ + const std::string::size_type sep = data.find_first_of(' '); + if(sep == std::string::npos || data.length() == sep + 1) { + if(errors) *errors += 1; + output_error("installfile:" + std::to_string(lineno), + "userpw: passphrase is required", + "expected format is: userpw [username] [crypt...]"); + return nullptr; + } + + std::string passphrase = data.substr(sep + 1); + if(!string_is_crypt(passphrase, "userpw", lineno)) { + if(errors) *errors += 1; + return nullptr; + } + + return new UserPassphrase(lineno, data.substr(0, sep), data.substr(sep + 1)); } bool UserPassphrase::validate(ScriptOptions) const { - return false; + /* If it's parseable, it's valid. */ + return true; } bool UserPassphrase::execute(ScriptOptions) const { diff --git a/tests/fixtures/0091-userpw-basic.installfile b/tests/fixtures/0091-userpw-basic.installfile new file mode 100644 index 0000000..2c3e842 --- /dev/null +++ b/tests/fixtures/0091-userpw-basic.installfile @@ -0,0 +1,7 @@ +network false +hostname test.machine +pkginstall adelie-base +rootpw $6$gumtLGmHwOVIRpQR$2M9PUO24hy5mofzWWf9a.YLbzOgOlUby1g0hDj.wG67E2wrrvys59fq02PPdxBdbgkLZFtjfEx6MHZwMBamwu/ +mount /dev/sda1 / +username awilfox +userpw awilfox $6$UZJm/vBmVgyIdMZr$ppKEulz/HY0/e7RcXXujQbcqDXkUYgIqNEVPQJO6.le9kUpz8GvvRezY3ifqUUEwjhSo9tTOMG7lhqjn8gGpH0 diff --git a/tests/fixtures/0092-userpw-without-pw.installfile b/tests/fixtures/0092-userpw-without-pw.installfile new file mode 100644 index 0000000..9b2b524 --- /dev/null +++ b/tests/fixtures/0092-userpw-without-pw.installfile @@ -0,0 +1,7 @@ +network false +hostname test.machine +pkginstall adelie-base +rootpw $6$gumtLGmHwOVIRpQR$2M9PUO24hy5mofzWWf9a.YLbzOgOlUby1g0hDj.wG67E2wrrvys59fq02PPdxBdbgkLZFtjfEx6MHZwMBamwu/ +mount /dev/sda1 / +username awilfox +userpw awilfox diff --git a/tests/fixtures/0093-userpw-unknown-name.installfile b/tests/fixtures/0093-userpw-unknown-name.installfile new file mode 100644 index 0000000..285a6a0 --- /dev/null +++ b/tests/fixtures/0093-userpw-unknown-name.installfile @@ -0,0 +1,8 @@ +network false +hostname test.machine +pkginstall adelie-base +rootpw $6$gumtLGmHwOVIRpQR$2M9PUO24hy5mofzWWf9a.YLbzOgOlUby1g0hDj.wG67E2wrrvys59fq02PPdxBdbgkLZFtjfEx6MHZwMBamwu/ +mount /dev/sda1 / +username awilfox +# Intentional misspelling +userpw awilcox $6$UZJm/vBmVgyIdMZr$ppKEulz/HY0/e7RcXXujQbcqDXkUYgIqNEVPQJO6.le9kUpz8GvvRezY3ifqUUEwjhSo9tTOMG7lhqjn8gGpH0 diff --git a/tests/fixtures/0094-userpw-duplicate.installfile b/tests/fixtures/0094-userpw-duplicate.installfile new file mode 100644 index 0000000..6416c6f --- /dev/null +++ b/tests/fixtures/0094-userpw-duplicate.installfile @@ -0,0 +1,9 @@ +network false +hostname test.machine +pkginstall adelie-base +rootpw $6$gumtLGmHwOVIRpQR$2M9PUO24hy5mofzWWf9a.YLbzOgOlUby1g0hDj.wG67E2wrrvys59fq02PPdxBdbgkLZFtjfEx6MHZwMBamwu/ +mount /dev/sda1 / +username awilfox +# Intentional duplication +userpw awilfox $6$UZJm/vBmVgyIdMZr$ppKEulz/HY0/e7RcXXujQbcqDXkUYgIqNEVPQJO6.le9kUpz8GvvRezY3ifqUUEwjhSo9tTOMG7lhqjn8gGpH0 +userpw awilfox $6$gumtLGmHwOVIRpQR$2M9PUO24hy5mofzWWf9a.YLbzOgOlUby1g0hDj.wG67E2wrrvys59fq02PPdxBdbgkLZFtjfEx6MHZwMBamwu/ diff --git a/tests/fixtures/0095-userpw-plaintext.installfile b/tests/fixtures/0095-userpw-plaintext.installfile new file mode 100644 index 0000000..c0dce02 --- /dev/null +++ b/tests/fixtures/0095-userpw-plaintext.installfile @@ -0,0 +1,7 @@ +network false +hostname test.machine +pkginstall adelie-base +rootpw $6$gumtLGmHwOVIRpQR$2M9PUO24hy5mofzWWf9a.YLbzOgOlUby1g0hDj.wG67E2wrrvys59fq02PPdxBdbgkLZFtjfEx6MHZwMBamwu/ +mount /dev/sda1 / +username awilfox +userpw awilfox Password123 diff --git a/tests/fixtures/0096-userpw-md5.installfile b/tests/fixtures/0096-userpw-md5.installfile new file mode 100644 index 0000000..79009bc --- /dev/null +++ b/tests/fixtures/0096-userpw-md5.installfile @@ -0,0 +1,7 @@ +network false +hostname test.machine +pkginstall adelie-base +rootpw $6$gumtLGmHwOVIRpQR$2M9PUO24hy5mofzWWf9a.YLbzOgOlUby1g0hDj.wG67E2wrrvys59fq02PPdxBdbgkLZFtjfEx6MHZwMBamwu/ +mount /dev/sda1 / +username awilfox +userpw awilfox $1$5f4dcc3b5aa765d61d8327deb882cf99 diff --git a/tests/fixtures/0097-userpw-missing.installfile b/tests/fixtures/0097-userpw-missing.installfile new file mode 100644 index 0000000..3811133 --- /dev/null +++ b/tests/fixtures/0097-userpw-missing.installfile @@ -0,0 +1,6 @@ +network false +hostname test.machine +pkginstall adelie-base +rootpw $6$gumtLGmHwOVIRpQR$2M9PUO24hy5mofzWWf9a.YLbzOgOlUby1g0hDj.wG67E2wrrvys59fq02PPdxBdbgkLZFtjfEx6MHZwMBamwu/ +mount /dev/sda1 / +username awilfox diff --git a/tests/spec/validator.rb b/tests/spec/validator.rb index 7fd8356..76f1c6f 100644 --- a/tests/spec/validator.rb +++ b/tests/spec/validator.rb @@ -568,6 +568,50 @@ RSpec.describe 'HorizonScript validation', :type => :aruba do expect(last_command_started).to have_output(/error: .*duplicate.*useralias/) end end + context "'userpw'" do + # Runner.Validate.userpw. + it "succeeds with username/passphrase combinations" do + use_fixture '0091-userpw-basic.installfile' + run_validate + expect(last_command_started).to have_output(PARSER_SUCCESS) + expect(last_command_started).to have_output(VALIDATOR_SUCCESS) + end + # Runner.Validate.userpw.Validity. + it "requires a passphrase to be provided" do + use_fixture '0092-userpw-without-pw.installfile' + run_validate + expect(last_command_started).to have_output(/error: .*userpw.*required/) + end + # Runner.Validate.userpw.Name. + it "fails with a username that wasn't given" do + use_fixture '0093-userpw-unknown-name.installfile' + run_validate + expect(last_command_started).to have_output(/error: .*userpw.*name/) + end + # Runner.Validate.userpw.Unique. + it "fails with more than one passphrase for an account" do + use_fixture '0094-userpw-duplicate.installfile' + run_validate + expect(last_command_started).to have_output(/error: .*duplicate.*userpw/) + end + # Runner.Validate.userpw.Crypt. + it "fails with a plain-text password" do + use_fixture '0095-userpw-plaintext.installfile' + run_validate + expect(last_command_started).to have_output(/error: .*userpw.*crypt/) + end + it "fails with an invalid encryption algorithm" do + use_fixture '0096-userpw-md5.installfile' + run_validate + expect(last_command_started).to have_output(/error: .*userpw.*crypt/) + end + # Runner.Validate.userpw.None. + it "warns when an account doesn't have a passphrase" do + use_fixture '0097-userpw-missing.installfile' + run_validate + expect(last_command_started).to have_output(/warning: .*passphrase/) + end + end end context "package specifications" do # no requirements for these, but I think obvious. |