From 9441c7a879b73e298cd15552997b97074ec0f9ba Mon Sep 17 00:00:00 2001 From: Craig Everett Date: Wed, 30 May 2018 12:59:49 +0900 Subject: [PATCH] wip --- zomp/lib/otpr/zx/0.1.0/src/zx.erl | 53 ++-- zomp/lib/otpr/zx/0.1.0/src/zx_key.erl | 22 +- zomp/lib/otpr/zx/0.1.0/src/zx_local.erl | 397 ++++++++++-------------- 3 files changed, 206 insertions(+), 266 deletions(-) diff --git a/zomp/lib/otpr/zx/0.1.0/src/zx.erl b/zomp/lib/otpr/zx/0.1.0/src/zx.erl index 1d9fd9c..e79a482 100644 --- a/zomp/lib/otpr/zx/0.1.0/src/zx.erl +++ b/zomp/lib/otpr/zx/0.1.0/src/zx.erl @@ -89,54 +89,71 @@ run(["runlocal" | ArgV]) -> run_local(ArgV); run(["init", "app", PackageString]) -> ok = compatibility_check([unix]), - zx_local:initialize(app, PackageString); + ok = zx_local:initialize(app, PackageString), + halt(0); run(["init", "lib", PackageString]) -> ok = compatibility_check([unix]), - zx_local:initialize(lib, PackageString); + ok = zx_local:initialize(lib, PackageString), + halt(0); run(["install", PackageFile]) -> - zx_local:assimilate(PackageFile); + ok = zx_local:assimilate(PackageFile), + halt(0); run(["set", "dep", PackageString]) -> - zx_local:set_dep(PackageString); + ok = zx_local:set_dep(PackageString), + halt(0); run(["set", "version", VersionString]) -> ok = compatibility_check([unix]), - zx_local:set_version(VersionString); + ok = zx_local:set_version(VersionString), + halt(0); run(["verup", Level]) -> ok = compatibility_check([unix]), - zx_local:verup(Level); + ok = zx_local:verup(Level), + halt(0); run(["list", "realms"]) -> - zx_loca:list_realms(); + ok = zx_local:list_realms(), + halt(0); run(["list", "packages", Realm]) -> ok = start(), - zx_local:list_packages(Realm); + ok = zx_local:list_packages(Realm), + halt(0); run(["list", "versions", PackageName]) -> ok = start(), - zx_local:list_versions(PackageName); + ok = zx_local:list_versions(PackageName), + halt(0); run(["add", "realm", RealmFile]) -> - zx_local:add_realm(RealmFile); + ok = zx_local:add_realm(RealmFile), + halt(0); run(["drop", "dep", PackageString]) -> PackageID = zx_lib:package_id(PackageString), - zx_local:drop_dep(PackageID); -run(["drop", "key", Realm, KeyName]) -> - zx_key:drop({Realm, KeyName}); + ok = zx_local:drop_dep(PackageID), + halt(0); run(["drop", "realm", Realm]) -> - zx_local:drop_realm(Realm); + ok = zx_local:drop_realm(Realm), + halt(0); run(["package"]) -> {ok, TargetDir} = file:get_cwd(), zx_local:package(TargetDir); run(["package", TargetDir]) -> case filelib:is_dir(TargetDir) of true -> - zx_local:package(TargetDir); + ok = zx_local:package(TargetDir), + halt(0); false -> ok = log(error, "Target directory ~tp does not exist!", [TargetDir]), halt(22) end; run(["dialyze"]) -> - zx_local:dialyze(); + ok = zx_local:dialyze(), + halt(0); run(["create", "user", Realm, Name]) -> - zx_local:create_user(Realm, Name); + ok = zx_local:create_user(Realm, Name), + halt(0); run(["create", "keypair"]) -> - zx_key:grow_a_pair(); + ok = zx_local:grow_a_pair(), + halt(0); +run(["drop", "key", Realm, KeyName]) -> + ok = zx_local:drop_key({Realm, KeyName}), + halt(0); run(["create", "plt"]) -> zx_local:create_plt(); run(["create", "realm"]) -> diff --git a/zomp/lib/otpr/zx/0.1.0/src/zx_key.erl b/zomp/lib/otpr/zx/0.1.0/src/zx_key.erl index e9e9ed7..e344a69 100644 --- a/zomp/lib/otpr/zx/0.1.0/src/zx_key.erl +++ b/zomp/lib/otpr/zx/0.1.0/src/zx_key.erl @@ -13,7 +13,7 @@ -license("GPL-3.0"). -export([ensure_keypair/1, have_public_key/1, have_private_key/1, - prompt_keygen/0, grow_a_pair/0, generate_rsa/1, + prompt_keygen/0, generate_rsa/1, load/2, verify/3]). -include("zx_logger.hrl"). @@ -102,22 +102,9 @@ prompt_keygen() -> end. --spec grow_a_pair() -> no_return(). -%% @private -%% Execute the key generation procedure for 16k RSA keys once and then terminate. - -grow_a_pair() -> - ok = file:set_cwd(zx_lib:zomp_dir()), - KeyID = prompt_keygen(), - case generate_rsa(KeyID) of - {ok, _, _} -> halt(0); - Error -> error_exit("grow_a_pair/0 error: ~tp", [Error], ?LINE) - end. - - -spec generate_rsa(KeyID) -> Result when KeyID :: zx:key_id(), - Result :: {ok, KeyFile, PubFile} + Result :: ok | {error, keygen_fail}, KeyFile :: file:filename(), PubFile :: file:filename(). @@ -144,10 +131,7 @@ generate_rsa({Realm, KeyName}) -> case check_key(KeyFile, PubFile) of true -> ok = file:delete(PemFile), - ok = log(info, "~ts and ~ts agree", [KeyFile, PubFile]), - ok = log(info, "Wrote private key to: ~ts.", [KeyFile]), - ok = log(info, "Wrote public key to: ~ts.", [PubFile]), - {ok, KeyFile, PubFile}; + log(info, "~ts and ~ts agree", [KeyFile, PubFile]); false -> ok = lists:foreach(fun file:delete/1, [PemFile, KeyFile, PubFile]), ok = log(error, "Something has gone wrong."), diff --git a/zomp/lib/otpr/zx/0.1.0/src/zx_local.erl b/zomp/lib/otpr/zx/0.1.0/src/zx_local.erl index e73c872..02a5c37 100644 --- a/zomp/lib/otpr/zx/0.1.0/src/zx_local.erl +++ b/zomp/lib/otpr/zx/0.1.0/src/zx_local.erl @@ -14,6 +14,7 @@ list_realms/0, list_packages/1, list_versions/1, add_realm/1, drop_dep/1, drop_key/1, drop_realm/1, verup/1, package/1, create_plt/0, dialyze/0, + grow_a_pair/0, drop_key/1, create_user/2, create_realm/0, create_realmfile/1]). -include("zx_logger.hrl"). @@ -22,7 +23,7 @@ %%% Functions --spec initialize(Type, PackageString) -> no_return() +-spec initialize(Type, PackageString) -> ok when Type :: app | lib, PackageString :: string(). %% @private @@ -72,8 +73,7 @@ initialize(Type, RawPackageString) -> " This project is currently listed as having no dependencies.~n" " If this is not true then run `zx set dep DepID` for each current dependency.~n" " (run `zx help` for more information on usage)~n", - ok = io:format(Message), - halt(0). + io:format(Message). -spec check_package_conflict(zx:package_id(), string()) -> ok. @@ -167,7 +167,7 @@ update_app_file({_, Name, Version}) -> zx_lib:write_terms(AppFile, [AppProfile]). --spec exec_shell(CMD) -> ok | no_return() +-spec exec_shell(CMD) -> ok when CMD :: string(). %% @private %% Print the output of an os:cmd/1 event only if there is any. @@ -182,13 +182,11 @@ exec_shell(CMD) -> end. --spec assimilate(PackageFile) -> PackageID - when PackageFile :: file:filename(), - PackageID :: zx:package_id(). +-spec assimilate(PackageFile) -> ok + when PackageFile :: file:filename(). %% @private %% Receives a path to a file containing package data, examines it, and copies it to a -%% canonical location under a canonical name, returning the PackageID of the package -%% contents. +%% canonical location under a canonical name. assimilate(PackageFile) -> Files = zx_lib:extract_zsp_or_die(PackageFile), @@ -212,11 +210,10 @@ assimilate(PackageFile) -> ok = file:set_cwd(CWD), Message = "~ts is now locally available.", {ok, PackageString} = zx_lib:package_string(PackageID), - ok = log(info, Message, [PackageString]), - halt(0). + log(info, Message, [PackageString]). --spec set_dep(Identifier :: string()) -> no_return(). +-spec set_dep(Identifier :: string()) -> ok. %% @private %% Set a specific dependency in the current project. If the project currently has a %% dependency on the same package then the version of that dependency is updated to @@ -236,6 +233,8 @@ set_dep(Identifier) -> set_dep({Realm, Name}, Version). +-spec set_dep(zx:package(), zx:version()) -> ok. + set_dep({Realm, Name}, Version) -> PackageID = {Realm, Name, Version}, {ok, Meta} = zx_lib:read_project_meta(), @@ -250,7 +249,7 @@ set_dep({Realm, Name}, Version) -> end. --spec set_dep(PackageID, Deps, Meta) -> no_return() +-spec set_dep(PackageID, Deps, Meta) -> ok when PackageID :: zx:package_id(), Deps :: [zx:package_id()], Meta :: [term()]. @@ -276,11 +275,10 @@ set_dep(PackageID = {Realm, Name, NewVersion}, Deps, Meta) -> [PackageID | Deps] end, NewMeta = maps:put(deps, NewDeps, Meta), - ok = zx_lib:write_project_meta(NewMeta), - halt(0). + zx_lib:write_project_meta(NewMeta). --spec set_version(VersionString) -> no_return() +-spec set_version(VersionString) -> ok when VersionString :: string(). %% @private %% Convert a version string to a new version, sanitizing it in the process and returning @@ -303,7 +301,7 @@ set_version(VersionString) -> update_version(Realm, Name, OldVersion, NewVersion, Meta). --spec update_version(Realm, Name, OldVersion, NewVersion, OldMeta) -> no_return() +-spec update_version(Realm, Name, OldVersion, NewVersion, OldMeta) -> ok when Realm :: zx:realm(), Name :: zx:name(), OldVersion :: zx:version(), @@ -322,22 +320,20 @@ update_version(Realm, Name, OldVersion, NewVersion, OldMeta) -> ok = zx_lib:write_project_meta(NewMeta), {ok, OldVS} = zx_lib:version_to_string(OldVersion), {ok, NewVS} = zx_lib:version_to_string(NewVersion), - ok = log(info, "Version changed from ~s to ~s.", [OldVS, NewVS]), - halt(0). + log(info, "Version changed from ~s to ~s.", [OldVS, NewVS]). --spec list_realms() -> no_return(). +-spec list_realms() -> ok. %% @private %% List all currently configured realms. The definition of a "configured realm" is a %% realm for which a .realm file exists in $ZOMP_HOME. The realms will be printed to %% stdout and the program will exit. list_realms() -> - ok = lists:foreach(fun(R) -> io:format("~ts~n", [R]) end, zx_lib:list_realms()), - halt(0). + lists:foreach(fun(R) -> io:format("~ts~n", [R]) end, zx_lib:list_realms()). --spec list_packages(zx:realm()) -> no_return(). +-spec list_packages(zx:realm()) -> ok. %% @private %% Contact the indicated realm and query it for a list of registered packages and print %% them to stdout. @@ -346,12 +342,10 @@ list_packages(Realm) -> ok = zx:start(), case zx_daemon:list_packages(Realm) of {ok, []} -> - ok = log(info, "Realm ~tp has no packages available.", [Realm]), - halt(0); + log(info, "Realm ~tp has no packages available.", [Realm]); {ok, Packages} -> Print = fun({R, N}) -> io:format("~ts-~ts~n", [R, N]) end, - ok = lists:foreach(Print, Packages), - halt(0); + lists:foreach(Print, Packages); {error, bad_realm} -> error_exit("Bad realm name.", ?LINE); {error, no_realm} -> @@ -362,7 +356,7 @@ list_packages(Realm) -> end. --spec list_versions(PackageName :: string()) -> no_return(). +-spec list_versions(PackageName :: string()) -> ok. %% @private %% List the available versions of the package indicated. The user enters a string-form %% package name (such as "otpr-zomp") and the return values will be full package strings @@ -376,20 +370,17 @@ list_versions(PackageName) -> {error, invalid_package_string} -> error_exit("~tp is not a valid package name.", [PackageName], ?LINE) end, - ok = zx:start(), case zx_daemon:list_versions(Package) of {ok, []} -> Message = "Package ~ts has no versions available.", - ok = log(info, Message, [PackageName]), - halt(0); + log(info, Message, [PackageName]); {ok, Versions} -> Print = fun(Version) -> {ok, PackageString} = zx_lib:package_string({Realm, Name, Version}), io:format("~ts~n", [PackageString]) end, - ok = lists:foreach(Print, Versions), - halt(0); + lists:foreach(Print, Versions); {error, bad_realm} -> error_exit("Bad realm name.", ?LINE); {error, bad_package} -> @@ -400,7 +391,7 @@ list_versions(PackageName) -> end. --spec add_realm(Path) -> no_return() +-spec add_realm(Path) -> ok when Path :: file:filename(). %% @private %% Add a .realm file to $ZOMP_HOME from a location in the filesystem. @@ -424,7 +415,7 @@ add_realm(Path) -> end. --spec add_realm(Path, Data) -> no_return() +-spec add_realm(Path, Data) -> ok when Path :: file:filename(), Data :: binary(). @@ -432,8 +423,7 @@ add_realm(Path, Data) -> case erl_tar:extract({binary, Data}, [compressed, {cwd, zx_lib:zomp_dir()}]) of ok -> {Realm, _} = string:take(filename:basename(Path), ".", true), - ok = log(info, "Realm ~ts is now visible to this system.", [Realm]), - halt(0); + log(info, "Realm ~ts is now visible to this system.", [Realm]); {error, invalid_tar_checksum} -> error_exit("~ts is not a valid realm file.", [Path], ?LINE); {error, eof} -> @@ -441,13 +431,20 @@ add_realm(Path, Data) -> end. --spec drop_dep(zx:package_id()) -> no_return(). +-spec drop_dep(zx:package_id()) -> ok. %% @private %% Remove the indicate dependency from the local project's zomp.meta record. drop_dep(PackageID) -> {ok, PackageString} = zx_lib:package_string(PackageID), - {ok, Meta} = zx_lib:read_project_meta(), + Meta = + case zx_lib:read_project_meta() of + {ok, M} -> + M; + {error, enoent} -> + ok = log(error, "zomp.meta not found. Is this a project directory?"), + halt(1) + end, Deps = maps:get(deps, Meta), case lists:member(PackageID, Deps) of true -> @@ -455,36 +452,13 @@ drop_dep(PackageID) -> NewMeta = maps:put(deps, NewDeps, Meta), ok = zx_lib:write_project_meta(NewMeta), Message = "~ts removed from dependencies.", - ok = log(info, Message, [PackageString]), - halt(0); + log(info, Message, [PackageString]); false -> - ok = log(info, "~ts not found in dependencies.", [PackageString]), - halt(0) + log(info, "~ts is not a dependency.", [PackageString]) end. --spec drop_key(zx:key_id()) -> no_return(). -%% @private -%% Given a KeyID, remove the related public and private keys from the keystore, if they -%% exist. If not, exit with a message that no keys were found, but do not return an -%% error exit value (this instruction is idempotent if used in shell scripts). - -drop_key({Realm, KeyName}) -> - ok = file:set_cwd(zx_lib:zomp_dir()), - KeyGlob = KeyName ++ ".{key,pub},der", - Pattern = filename:join([zx_lib:zomp_dir(), "key", Realm, KeyGlob]), - case filelib:wildcard(Pattern) of - [] -> - ok = log(warning, "Key ~ts/~ts not found", [Realm, KeyName]), - halt(0); - Files -> - ok = lists:foreach(fun file:delete/1, Files), - ok = log(info, "Keyset ~ts/~ts removed", [Realm, KeyName]), - halt(0) - end. - - --spec drop_realm(zx:realm()) -> no_return(). +-spec drop_realm(zx:realm()) -> ok. drop_realm(Realm) -> ok = file:set_cwd(zx_lib:zomp_dir()), @@ -501,11 +475,9 @@ drop_realm(Realm) -> ok = file:delete(RealmConf), ok = drop_prime(Realm), ok = clear_keys(Realm), - ok = log(info, "All traces of realm ~ts have been removed."), - halt(0); + log(info, "All traces of realm ~ts have been removed."); _ -> - ok = log(info, "Aborting."), - halt(0) + log(info, "Aborting.") end; false -> ok = log(warning, "Realm conf ~ts not found.", [RealmConf]), @@ -539,7 +511,7 @@ clear_keys(Realm) -> end. --spec verup(Level) -> no_return() +-spec verup(Level) -> ok when Level :: string(). %% @private %% Convert input string arguments to acceptable atoms for use in update_version/1. @@ -550,7 +522,7 @@ verup("patch") -> version_up(patch); verup(_) -> zx:usage_exit(22). --spec version_up(Level) -> no_return() +-spec version_up(Level) -> ok when Level :: major | minor | patch. @@ -570,7 +542,7 @@ version_up(Arg) -> version_up(Arg, PackageID, Meta). --spec version_up(Level, PackageID, Meta) -> no_return() +-spec version_up(Level, PackageID, Meta) -> ok when Level :: major | minor | patch @@ -612,7 +584,7 @@ package(TargetDir) -> [] -> ok = log(info, "Need to generate key"), KeyID = zx_key:prompt_keygen(), - {ok, _, _} = zx_key:generate_rsa(KeyID), + ok = zx_key:generate_rsa(KeyID), package(KeyID, TargetDir); [KeyName] -> KeyID = {Realm, KeyName}, @@ -722,7 +694,7 @@ default_plt() -> filename:join(zx_lib:zomp_dir(), "basic.plt"). --spec dialyze() -> no_return(). +-spec dialyze() -> ok. %% @private %% Preps a copy of this script for typechecking with Dialyzer. %% TODO: Create a package_id() based version of this to handle dialyzation of complex @@ -740,7 +712,7 @@ dialyze() -> EvilTwin = filename:join(TmpDir, filename:basename(Me ++ ".erl")), ok = log(info, "Temporarily reconstructing ~tp as ~tp", [Me, EvilTwin]), Sed = io_lib:format("sed 's/^#!.*$//' ~s > ~s", [Me, EvilTwin]), - "" = os:cmd(Sed), + ok = exec_shell(Sed), ok = case dialyzer:run([{init_plt, PLT}, {from, src_code}, {files, [EvilTwin]}]) of [] -> io:format("Dialyzer found no errors and returned no warnings! Yay!~n"); @@ -749,11 +721,42 @@ dialyze() -> || {Tag, {_, Line}, Msg} <- Warnings], lists:foreach(fun io:format/1, Mine) end, - ok = file:delete(EvilTwin), - halt(0). + file:delete(EvilTwin). --spec create_user(zx:realm(), zx:user_name()) -> no_return(). +-spec grow_a_pair() -> ok. +%% @private +%% Execute the key generation procedure for 16k RSA keys once and then terminate. + +grow_a_pair() -> + ok = file:set_cwd(zx_lib:zomp_dir()), + KeyID = zx_key:prompt_keygen(), + case zx_key:generate_rsa(KeyID) of + ok -> ok; + Error -> error_exit("grow_a_pair/0 error: ~tp", [Error], ?LINE) + end. + + +-spec drop_key(zx:key_id()) -> ok. +%% @private +%% Given a KeyID, remove the related public and private keys from the keystore, if they +%% exist. If not, exit with a message that no keys were found, but do not return an +%% error exit value (this instruction is idempotent if used in shell scripts). + +drop_key({Realm, KeyName}) -> + ok = file:set_cwd(zx_lib:zomp_dir()), + KeyGlob = KeyName ++ ".{key,pub},der", + Pattern = filename:join([zx_lib:zomp_dir(), "key", Realm, KeyGlob]), + case filelib:wildcard(Pattern) of + [] -> + log(warning, "Key ~ts/~ts not found", [Realm, KeyName]); + Files -> + ok = lists:foreach(fun file:delete/1, Files), + log(info, "Keyset ~ts/~ts removed", [Realm, KeyName]) + end. + + +-spec create_user(zx:realm(), zx:user_name()) -> ok. %% @private %% Validate the realm and username provided, prompt the user to either select a keypair %% to use or generate a new one, and bundle a .zuser file for conveyance of the user @@ -762,11 +765,10 @@ dialyze() -> create_user(Realm, Username) -> Message = "Would be generating a user file for {~160tp, ~160to}.", - ok = log(info, Message, [Realm, Username]), - halt(0). + log(info, Message, [Realm, Username]). --spec create_realm() -> no_return(). +-spec create_realm() -> ok. %% @private %% Prompt the user to input the information necessary to create a new zomp realm, %% package the data appropriately for the server and deliver the final keys and @@ -796,39 +798,34 @@ create_realm() -> end. --spec create_realm(Realm) -> no_return() +-spec create_realm(Realm) -> ok when Realm :: zx:realm(). create_realm(Realm) -> - ExAddress = prompt_external_address(), - create_realm(Realm, ExAddress). + Address = prompt_address(), + create_realm(Realm, Address). --spec prompt_external_address() -> Result +-spec prompt_address() -> Result when Result :: inet:hostname() | inet:ip_address(). -prompt_external_address() -> - Message = external_address_prompt(), +prompt_address() -> + Message = + "~n" + " Enter a static, valid hostname or IPv4 or IPv6 address at which this host " + "can be reached from the public internet (or internal network if it will never " + "need to be reached from the internet).~n" + " DO NOT INCLUDE A PORT NUMBER IN THIS STEP~n", ok = io:format(Message), case zx_tty:get_input() of "" -> ok = io:format("You need to enter an address.~n"), - prompt_external_address(); + prompt_address(); String -> parse_address(String) end. --spec external_address_prompt() -> string(). - -external_address_prompt() -> - "~n" - " Enter a static, valid hostname or IPv4 or IPv6 address at which this host " - "can be reached from the public internet (or internal network if it will never " - "need to be reached from the internet).~n" - " DO NOT INCLUDE A PORT NUMBER IN THIS STEP~n". - - -spec parse_address(string()) -> inet:hostname() | inet:ip_address(). parse_address(String) -> @@ -838,35 +835,19 @@ parse_address(String) -> end. --spec create_realm(Realm, ExAddress) -> no_return() - when Realm :: zx:realm(), - ExAddress :: inet:hostname() | inet:ip_address(). +-spec create_realm(Realm, Address) -> ok + when Realm :: zx:realm(), + Address :: inet:hostname() | inet:ip_address(). -create_realm(Realm, ExAddress) -> +create_realm(Realm, Address) -> Message = "~n" " Enter the public (external) port number at which this service should be " "available. (This might be different from the local port number if you are " "forwarding ports or have a complex network layout.)~n", ok = io:format(Message), - ExPort = prompt_port_number(11311), - create_realm(Realm, ExAddress, ExPort). - - --spec create_realm(Realm, ExAddress, ExPort) -> no_return() - when Realm :: zx:realm(), - ExAddress :: inet:hostname() | inet:ip_address(), - ExPort :: inet:port_number(). - -create_realm(Realm, ExAddress, ExPort) -> - Message = - "~n" - " Enter the local (internal/LAN) port number at which this service should be " - "available. (This might be different from the public port visible from the " - "internet if you are port forwarding or have a complex network layout.)~n", - ok = io:format(Message), - InPort = prompt_port_number(11311), - create_realm(Realm, ExAddress, ExPort, InPort). + Port = prompt_port_number(11311), + create_realm(Realm, Address, Port). -spec prompt_port_number(Current) -> Result @@ -898,13 +879,13 @@ prompt_port_number(Current) -> end. --spec create_realm(Realm, ExAddress, ExPort, InPort) -> no_return() - when Realm :: zx:realm(), - ExAddress :: inet:hostname() | inet:ip_address(), - ExPort :: inet:port_number(), - InPort :: inet:port_number(). +-spec create_realm(Realm, Address, Port) -> ok + when Realm :: zx:realm(), + Address :: inet:hostname() | inet:ip_address(), + Port :: inet:port_number(), + Port :: inet:port_number(). -create_realm(Realm, ExAddress, ExPort, InPort) -> +create_realm(Realm, Address, Port) -> Instructions = "~n" " Enter a username for the realm sysop.~n" @@ -914,21 +895,20 @@ create_realm(Realm, ExAddress, ExPort, InPort) -> UserName = zx_tty:get_input(), case zx_lib:valid_lower0_9(UserName) of true -> - create_realm(Realm, ExAddress, ExPort, InPort, UserName); + create_realm(Realm, Address, Port, UserName); false -> ok = io:format("Bad username ~tp. Try again.~n", [UserName]), - create_realm(Realm, ExAddress, ExPort, InPort) + create_realm(Realm, Address, Port) end. --spec create_realm(Realm, ExAddress, ExPort, InPort, UserName) -> no_return() - when Realm :: zx:realm(), - ExAddress :: inet:hostname() | inet:ip_address(), - ExPort :: inet:port_number(), - InPort :: inet:port_number(), - UserName :: string(). +-spec create_realm(Realm, Address, Port, UserName) -> ok + when Realm :: zx:realm(), + Address :: inet:hostname() | inet:ip_address(), + Port :: inet:port_number(), + UserName :: string(). -create_realm(Realm, ExAddress, ExPort, InPort, UserName) -> +create_realm(Realm, Address, Port, UserName) -> Instructions = "~n" " Enter an email address for the realm sysop.~n" @@ -940,125 +920,73 @@ create_realm(Realm, ExAddress, ExPort, InPort, UserName) -> [User, Host] = string:lexemes(Email, "@"), case {zx_lib:valid_lower0_9(User), zx_lib:valid_label(Host)} of {true, true} -> - create_realm(Realm, ExAddress, ExPort, InPort, UserName, Email); + create_realm(Realm, Address, Port, UserName, Email); {false, true} -> Message = "The user part of the email address seems invalid. Try again.~n", ok = io:format(Message), - create_realm(Realm, ExAddress, ExPort, InPort, UserName); + create_realm(Realm, Address, Port, UserName); {true, false} -> Message = "The host part of the email address seems invalid. Try again.~n", ok = io:format(Message), - create_realm(Realm, ExAddress, ExPort, InPort, UserName); + create_realm(Realm, Address, Port, UserName); {false, false} -> Message = "This email address seems like its totally bonkers. Try again.~n", ok = io:format(Message), - create_realm(Realm, ExAddress, ExPort, InPort, UserName) + create_realm(Realm, Address, Port, UserName) end. --spec create_realm(Realm, ExAddress, ExPort, InPort, UserName, Email) -> - no_return() - when Realm :: zx:realm(), - ExAddress :: inet:hostname() | inet:ip_address(), - ExPort :: inet:port_number(), - InPort :: inet:port_number(), - UserName :: string(), - Email :: string(). +-spec create_realm(Realm, Address, Port, UserName, Email) -> ok + when Realm :: zx:realm(), + Address :: inet:hostname() | inet:ip_address(), + Port :: inet:port_number(), + UserName :: string(), + Email :: string(). -create_realm(Realm, ExAddress, ExPort, InPort, UserName, Email) -> +create_realm(Realm, Address, Port, UserName, Email) -> Instructions = "~n" " Enter the real name (or whatever name people recognize) for the sysop.~n" " There are no rules for this one. Any valid UTF-8 printables are legal.~n", ok = io:format(Instructions), RealName = zx_tty:get_input(), - create_realm(Realm, ExAddress, ExPort, InPort, UserName, Email, RealName). + create_realm(Realm, Address, Port, UserName, Email, RealName). --spec create_realm(Realm, ExAddress, ExPort, InPort, UserName, Email, RealName) -> no_return() - when Realm :: zx:realm(), - ExAddress :: inet:hostname() | inet:ip_address(), - ExPort :: inet:port_number(), - InPort :: inet:port_number(), - UserName :: string(), - Email :: string(), - RealName :: string(). +-spec create_realm(Realm, Address, Port, UserName, Email, RealName) -> ok + when Realm :: zx:realm(), + Address :: inet:hostname() | inet:ip_address(), + Port :: inet:port_number(), + UserName :: string(), + Email :: string(), + RealName :: string(). -create_realm(Realm, ExAddress, ExPort, InPort, UserName, Email, RealName) -> +create_realm(Realm, Address, Port, UserName, Email, RealName) -> ok = io:format("~nGenerating keys. This might take a while, so settle in...~n"), - {ok, RealmKey, RealmPub} = zx_key:generate_rsa({Realm, Realm ++ ".1.realm"}), - {ok, PackageKey, PackagePub} = zx_key:generate_rsa({Realm, Realm ++ ".1.package"}), - {ok, SysopKey, SysopPub} = zx_key:generate_rsa({Realm, UserName ++ ".1"}), - ok = log(info, "Generated 16k RSA pair ~ts ~ts", [RealmKey, RealmPub]), - ok = log(info, "Generated 16k RSA pair ~ts ~ts", [PackageKey, PackagePub]), - ok = log(info, "Generated 16k RSA pair ~ts ~ts", [SysopKey, SysopPub]), - + KeyName = UserName ++ "-root", + ok = zx_key:generate_rsa({Realm, KeyName}), Timestamp = calendar:now_to_universal_time(erlang:timestamp()), - - {ok, RealmPubData} = file:read_file(RealmPub), - RealmPubRecord = - {{Realm, filename:basename(RealmPub, ".pub.der")}, - realm, - {realm, Realm}, - crypto:hash(sha512, RealmPubData), - Timestamp}, - {ok, PackagePubData} = file:read_file(PackagePub), - PackagePubRecord = - {{Realm, filename:basename(PackagePub, ".pub.der")}, - package, - {realm, Realm}, - crypto:hash(sha512, PackagePubData), - Timestamp}, - UserRecord = - {{Realm, UserName}, - [filename:basename(SysopPub, ".pub.der")], - Email, - RealName}, - RealmSettings = + RealmConf = + [{realm, Realm}, + {prime, {Address, Port}}, + {sysop, UserName}, + {key, KeyName}], + UserFile = [{realm, Realm}, - {revision, 0}, - {prime, {ExAddress, ExPort}}, - {private, []}, - {mirrors, []}, - {sysops, [UserRecord]}, - {realm_keys, [RealmPubRecord]}, - {package_keys, [PackagePubRecord]}], - ZompSettings = - [{managed, [Realm]}, - {external_address, ExAddress}, - {external_port, ExPort}, - {internal_port, InPort}], + {username, UserName}, + {realmname, RealName}, + {contact_info, {"email", Email}}, + {keys, [KeyName]}], {ok, CWD} = file:get_cwd(), - {ok, TempDir} = mktemp_dir("zomp"), - ok = file:set_cwd(TempDir), - KeyDir = filename:join("key", Realm), - ok = filelib:ensure_dir(KeyDir), - ok = file:make_dir(KeyDir), - KeyCopy = - fun(K) -> - {ok, _} = file:copy(K, filename:join(KeyDir, filename:basename(K))), - ok - end, - - PublicZRF = filename:join(CWD, Realm ++ ".zrf"), - RealmFN = Realm ++ ".realm", - ok = zx_lib:write_terms(RealmFN, RealmSettings), - ok = KeyCopy(PackagePub), - ok = KeyCopy(RealmPub), - ok = erl_tar:create(PublicZRF, [RealmFN, "key"], [compressed]), - - PrimeZRF = filename:join(CWD, Realm ++ ".zpf"), - ok = KeyCopy(SysopPub), - ok = zx_lib:write_terms("zomp.conf", ZompSettings), - ok = erl_tar:create(PrimeZRF, [RealmFN, "zomp.conf", "key"], [compressed]), - - KeyBundle = filename:join(CWD, Realm ++ ".zkf"), - ok = lists:foreach(KeyCopy, [PackageKey, RealmKey, SysopKey]), - ok = erl_tar:create(KeyBundle, [KeyDir], [compressed]), - - ok = file:set_cwd(CWD), - ok = zx_lib:rm_rf(TempDir), + ok = file:set_cwd(zx_lib:path(etc)), + PubKey = zx_key:name(pub, KeyName), + ConfFile = filename:join(Realm, "realm.conf"), + ok = file:make_dir(Realm), + ok = zx_lib:write_terms(ConfFile, RealmConf), + ZRF = + ok = erl_tar:create(ZRF, [ConfFile, PubKey], [compressed]), + Message = "===========================================================================~n" @@ -1097,8 +1025,19 @@ create_realm(Realm, ExAddress, ExPort, InPort, UserName, Email, RealName) -> PrimeZRF, PublicZRF, PublicZRF, KeyBundle], - ok = io:format(Message, Substitutions), - halt(0). + io:format(Message, Substitutions). + + +-spec configure_zomp() - ok. + +configure_zomp() -> + ZompSettings = + [{node, 16}, + {vampire, 16}, + {leaf, 256}, + {listen_port, 11311}, + {public_port, 11311}], + io:format("~tp~n", [ZompSettings]). -spec mktemp_dir(Prefix) -> Result