From 799b2fc3939bf4e30ed404a67aa7697ae352f5fe Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Fri, 18 Oct 2019 18:31:19 -0500 Subject: hscript: Add stub User* classes --- hscript/script.cc | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- hscript/user.cc | 88 ++++++++++++++++++++++++++++++++++++++++++++ hscript/user.hh | 81 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 269 insertions(+), 7 deletions(-) diff --git a/hscript/script.cc b/hscript/script.cc index 83957f8..1cc6f5d 100644 --- a/hscript/script.cc +++ b/hscript/script.cc @@ -67,6 +67,15 @@ const std::map valid_keys = { namespace Horizon { +/*! Describes a user account. */ +struct UserDetail { + std::unique_ptr name; + std::unique_ptr alias; + std::unique_ptr passphrase; + std::unique_ptr icon; + std::vector< std::unique_ptr > groups; +}; + struct Script::ScriptPrivate { /*! Determines whether or not to enable networking. */ std::unique_ptr network; @@ -86,6 +95,9 @@ struct Script::ScriptPrivate { /*! APK repositories */ std::vector< std::unique_ptr > repos; + /*! User account information */ + std::map< std::string, std::unique_ptr > accounts; + /*! Disk identification keys */ std::vector< std::unique_ptr > diskids; @@ -104,29 +116,35 @@ struct Script::ScriptPrivate { err_str += " at installfile:" + std::to_string(OBJ->lineno());\ if(errors) *errors += 1;\ output_error("installfile:" + std::to_string(lineno),\ - "duplicate value for key '" + KEY + "'", err_str); + "duplicate value for key '" + std::string(KEY) + "'",\ + err_str); using namespace Horizon::Keys; if(key_name == "network") { + if(this->network) { - DUPLICATE_ERROR(this->network, std::string("network"), + DUPLICATE_ERROR(this->network, "network", this->network->test() ? "true" : "false") return false; } std::unique_ptr net(dynamic_cast(obj)); this->network = std::move(net); return true; + } else if(key_name == "hostname") { + if(this->hostname) { - DUPLICATE_ERROR(this->hostname, std::string("hostname"), + DUPLICATE_ERROR(this->hostname, "hostname", this->hostname->value()) return false; } std::unique_ptr name(dynamic_cast(obj)); this->hostname = std::move(name); return true; + } else if(key_name == "pkginstall") { + PkgInstall *install = dynamic_cast(obj); for(auto &pkg : install->packages()) { if(opts.test(StrictMode) && packages.find(pkg) != packages.end()) { @@ -140,7 +158,9 @@ struct Script::ScriptPrivate { } delete install; return true; + } else if(key_name == "rootpw") { + if(this->rootpw) { DUPLICATE_ERROR(this->rootpw, std::string("rootpw"), "an encrypted passphrase") @@ -151,29 +171,110 @@ struct Script::ScriptPrivate { ); this->rootpw = std::move(name); return true; + } else if(key_name == "mount") { + std::unique_ptr mount(dynamic_cast(obj)); this->mounts.push_back(std::move(mount)); return true; + } else if(key_name == "netaddress") { + std::unique_ptr addr(dynamic_cast(obj)); this->addresses.push_back(std::move(addr)); return true; + } else if(key_name == "netssid") { + std::unique_ptr ssid(dynamic_cast(obj)); this->ssids.push_back(std::move(ssid)); return true; + } else if(key_name == "repository") { + std::unique_ptr repo(dynamic_cast(obj)); this->repos.push_back(std::move(repo)); return true; + } else if(key_name == "diskid") { + std::unique_ptr diskid(dynamic_cast(obj)); this->diskids.push_back(std::move(diskid)); return true; + + } else if(key_name == "username") { + + if(accounts.size() >= 255) { + output_error("installfile:" + std::to_string(lineno), + "username: too many users", + "you may only specify 255 users"); + return false; + } + std::unique_ptr name(dynamic_cast(obj)); + if(accounts.find(name->value()) != accounts.end()) { + DUPLICATE_ERROR((*accounts.find(name->value())).second->name, + "username", "assigned") + return false; + } + std::unique_ptr detail(new UserDetail); + detail->name = std::move(name); + accounts.insert(std::make_pair(name->value(), std::move(detail))); + return true; + +#define GET_USER_DETAIL(OBJ, KEY) \ + if(accounts.find(OBJ->username()) == accounts.end()) {\ + output_error("installfile:" + std::to_string(lineno),\ + std::string(KEY) + ": account name " + OBJ->username() +\ + " is unknown");\ + return false;\ + }\ + UserDetail *detail = (*accounts.find(OBJ->username())).second.get(); + + } else if(key_name == "useralias") { + + std::unique_ptr alias(dynamic_cast(obj)); + GET_USER_DETAIL(alias, "useralias") + if(detail->alias) { + DUPLICATE_ERROR(detail->alias, "useralias", detail->alias->alias()) + return false; + } + detail->alias = std::move(alias); + return true; + + } else if(key_name == "userpw") { + + std::unique_ptr pw(dynamic_cast(obj)); + GET_USER_DETAIL(pw, "userpw") + if(detail->passphrase) { + DUPLICATE_ERROR(detail->passphrase, "userpw", + "an encrypted passphrase") + return false; + } + detail->passphrase = std::move(pw); + return true; + + } else if(key_name == "usericon") { + + std::unique_ptr icon(dynamic_cast(obj)); + GET_USER_DETAIL(icon, "usericon") + if(detail->icon) { + DUPLICATE_ERROR(detail->icon, "usericon", detail->icon->icon()) + return false; + } + detail->icon = std::move(icon); + return true; + + } else if(key_name == "usergroups") { + + std::unique_ptr grp(dynamic_cast(obj)); + GET_USER_DETAIL(grp, "usergroups") + detail->groups.push_back(std::move(grp)); + return true; + } else { return false; } + #undef DUPLICATE_ERROR } }; diff --git a/hscript/user.cc b/hscript/user.cc index 4d00cb2..92fed4e 100644 --- a/hscript/user.cc +++ b/hscript/user.cc @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include "user.hh" @@ -20,6 +21,23 @@ using namespace Horizon::Keys; +const static std::set system_names = { + "root", "bin", "daemon", "adm", "lp", "sync", "shutdown", "halt", "mail", + "news", "uucp", "operator", "man", "postmaster", "cron", "ftp", "sshd", + "at", "squid", "xfs", "games", "postgres", "cyrus", "vpopmail", "utmp", + "catchlog", "alias", "qmaild", "qmailp", "qmailq", "qmailr", "qmails", + "qmaill", "ntp", "smmsp", "guest", "nobody" +}; + +const static std::set system_groups = { + "root", "bin", "daemon", "sys", "adm", "tty", "disk", "lp", "mem", "kmem", + "wheel", "floppy", "mail", "news", "uucp", "man", "cron", "console", + "audio", "cdrom", "dialout", "ftp", "sshd", "input", "at", "tape", "video", + "netdev", "readproc", "squid", "xfs", "kvm", "games", "shadow", "postgres", + "cdrw", "usb", "vpopmail", "users", "catchlog", "ntp", "nofiles", "qmail", + "qmaill", "smmsp", "locate", "abuild", "utmp", "ping", "nogroup", "nobody" +}; + 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') @@ -85,3 +103,73 @@ bool RootPassphrase::execute(ScriptOptions options) const { return true; /* LCOV_EXCL_STOP */ } + + +Key *Username::parseFromData(const std::string &data, int lineno, int *errors, + int *warnings) { + return nullptr; +} + +bool Username::validate(ScriptOptions) const { + return false; +} + +bool Username::execute(ScriptOptions) const { + return false; +} + + +Key *UserAlias::parseFromData(const std::string &data, int lineno, int *errors, + int *warnings) { + return nullptr; +} + +bool UserAlias::validate(ScriptOptions) const { + return false; +} + +bool UserAlias::execute(ScriptOptions) const { + return false; +} + + +Key *UserPassphrase::parseFromData(const std::string &data, int lineno, + int *errors, int *warnings) { + return nullptr; +} + +bool UserPassphrase::validate(ScriptOptions) const { + return false; +} + +bool UserPassphrase::execute(ScriptOptions) const { + return false; +} + + +Key *UserIcon::parseFromData(const std::string &data, int lineno, int *errors, + int *warnings) { + return nullptr; +} + +bool UserIcon::validate(ScriptOptions) const { + return false; +} + +bool UserIcon::execute(ScriptOptions) const { + return false; +} + + +Key *UserGroups::parseFromData(const std::string &data, int lineno, + int *errors, int *warnings) { + return nullptr; +} + +bool UserGroups::validate(ScriptOptions) const { + return false; +} + +bool UserGroups::execute(ScriptOptions) const { + return false; +} diff --git a/hscript/user.hh b/hscript/user.hh index 3f4d23b..b8d5386 100644 --- a/hscript/user.hh +++ b/hscript/user.hh @@ -13,6 +13,8 @@ #ifndef __HSCRIPT_USER_HH_ #define __HSCRIPT_USER_HH_ +#include +#include #include "key.hh" namespace Horizon { @@ -20,28 +22,99 @@ namespace Keys { class RootPassphrase : public StringKey { private: - RootPassphrase(int _line, const std::string my_pw) : + RootPassphrase(int _line, const std::string &my_pw) : StringKey(_line, my_pw) {} public: - static Key *parseFromData(const std::string &data, int lineno, int *errors, - int *warnings); + static Key *parseFromData(const std::string &, int, int*, int*); bool validate(ScriptOptions) const override; bool execute(ScriptOptions) const override; }; class Username : public StringKey { +private: + Username(int _line, const std::string &name) : + StringKey(_line, name) {} +public: + static Key *parseFromData(const std::string &, int, int*, int*); + bool validate(ScriptOptions) const override; + bool execute(ScriptOptions) const override; }; class UserAlias : public Key { +private: + const std::string _username; + const std::string _alias; + + UserAlias(int _line, const std::string &_n, const std::string &_a) : + Key(_line), _username(_n), _alias(_a) {} +public: + static Key *parseFromData(const std::string &, int, int*, int*); + + /*! Retrieve the username for this alias. */ + const std::string &username() const { return this->_username; } + /*! Retrieve the alias for the account. */ + const std::string &alias() const { return this->_alias; } + + bool validate(ScriptOptions) const override; + bool execute(ScriptOptions) const override; }; -class UserPassphrase : public StringKey { +class UserPassphrase : public Key { +private: + const std::string _username; + const std::string _passphrase; + + UserPassphrase(int _line, const std::string &_n, const std::string &_p) : + Key(_line), _username(_n), _passphrase(_p) {} +public: + static Key *parseFromData(const std::string &, int, int*, int*); + + /*! Retrieve the username for this passphrase. */ + const std::string &username() const { return this->_username; } + /*! Retrieve the passphrase for the account. */ + const std::string &passphrase() const { return this->_passphrase; } + + bool validate(ScriptOptions) const override; + bool execute(ScriptOptions) const override; }; class UserIcon : public Key { +private: + const std::string _username; + const std::string _icon_path; + + UserIcon(int _line, const std::string &_n, const std::string &_i) : + Key(_line), _username(_n), _icon_path(_i) {} +public: + static Key *parseFromData(const std::string &, int, int*, int*); + + /*! Retrieve the username for this icon. */ + const std::string &username() const { return this->_username; } + /*! Retrieve the icon path for the account. */ + const std::string &icon() const { return this->_icon_path; } + + bool validate(ScriptOptions) const override; + bool execute(ScriptOptions) const override; }; class UserGroups : public Key { +private: + const std::string _username; + const std::set _groups; + + UserGroups(int _line, const std::string &_n, + const std::set &_g) : + Key(_line), _username(_n), _groups(_g) {} +public: + static Key *parseFromData(const std::string &, int, int*, int*); + + /*! Retrieve the username for this group set. */ + const std::string &username() const { return this->_username; } + /*! Retrieve the groups for the account. */ + const std::set &groups() const { return this->_groups; } + + bool validate(ScriptOptions) const override; + bool execute(ScriptOptions) const override; }; } -- cgit v1.2.3-70-g09d2