wip
This commit is contained in:
parent
5d7d6599a9
commit
cc4d55288d
186
zx
186
zx
@ -668,7 +668,7 @@ package(TargetDir) ->
|
||||
[] ->
|
||||
ok = log(info, "Need to generate key"),
|
||||
KeyID = prompt_keygen(),
|
||||
ok = generate_rsa(KeyID),
|
||||
{ok, _, _} = generate_rsa(KeyID),
|
||||
package(KeyID, TargetDir);
|
||||
[KeyName] ->
|
||||
KeyID = {Realm, KeyName},
|
||||
@ -1144,11 +1144,14 @@ prompt_keygen() ->
|
||||
case {valid_lower0_9(Realm), valid_label(KeyName)} of
|
||||
{true, true} ->
|
||||
{Realm, KeyName};
|
||||
{false, _} ->
|
||||
{false, true} ->
|
||||
ok = io:format("Bad realm name ~tp. Try again.~n", [Realm]),
|
||||
prompt_keygen();
|
||||
{true, false} ->
|
||||
ok = io:format("Bad key name ~tp. Try again.~n", [KeyName]),
|
||||
prompt_keygen();
|
||||
{false, false} ->
|
||||
ok = io:format("NUTS! Both the key and realm names are illegal. Try again.~n"),
|
||||
prompt_keygen()
|
||||
end.
|
||||
|
||||
@ -1161,7 +1164,7 @@ create_keypair() ->
|
||||
ok = file:set_cwd(zomp_dir()),
|
||||
KeyID = prompt_keygen(),
|
||||
case generate_rsa(KeyID) of
|
||||
ok -> halt(0);
|
||||
{ok, _, _} -> halt(0);
|
||||
Error -> error_exit("create_keypair/0 failed with ~tp", [Error], ?FILE, ?LINE)
|
||||
end.
|
||||
|
||||
@ -1198,7 +1201,7 @@ generate_rsa({Realm, KeyName}) ->
|
||||
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;
|
||||
{ok, KeyFile, PubFile};
|
||||
false ->
|
||||
ok = lists:foreach(fun file:delete/1, [PemFile, KeyFile, PubFile]),
|
||||
ok = log(error, "Something has gone wrong."),
|
||||
@ -1400,11 +1403,12 @@ dialyze() ->
|
||||
%%% Create Realm & Sysop
|
||||
|
||||
create_realm() ->
|
||||
RealmMessage =
|
||||
"~n Enter a name for your new realm.~n"
|
||||
Instructions =
|
||||
"~n"
|
||||
" Enter a name for your new realm.~n"
|
||||
" Valid names can contain only lower-case letters, numbers and the underscore.~n"
|
||||
" Valid names must begin with a lower-case letter.~n",
|
||||
ok = io:format(RealmMessage),
|
||||
ok = io:format(Instructions),
|
||||
Realm = get_input(),
|
||||
case valid_lower0_9(Realm) of
|
||||
true ->
|
||||
@ -1422,32 +1426,144 @@ create_realm() ->
|
||||
end.
|
||||
|
||||
create_realm(Realm) ->
|
||||
UserNameMessage =
|
||||
"~n Enter a username for the realm sysop.~n"
|
||||
HostInstructions =
|
||||
"~n"
|
||||
" Enter the prime (permanent) server's publicly accessible hostname or~n"
|
||||
" address. If prime is identified by an address and not a name, enter it~n"
|
||||
" as either a normal IPv4 dot-notation or IPv6 colon-notation.~n"
|
||||
" Note that address ranges will not be checked for validity.~n",
|
||||
ok = io:format(HostInstructions),
|
||||
HostString = get_input(),
|
||||
Host =
|
||||
case inet:parse_address(HostString) of
|
||||
{ok, Address} -> Address;
|
||||
{error, einval} -> HostString
|
||||
end,
|
||||
PortInstructions =
|
||||
" Enter the port number the host will be listening on.~n"
|
||||
" The port can be any number from 1 to 65535.~n"
|
||||
" [Press enter for the default: 11311]~n",
|
||||
ok = io:format(PortInstructions),
|
||||
case get_input() of
|
||||
"" ->
|
||||
create_realm(Realm, {HostString, 11311});
|
||||
S ->
|
||||
try
|
||||
case list_to_integer(S) of
|
||||
Port when 16#ffff >= Port, Port > 0 ->
|
||||
create_realm(Realm, {Host, Port});
|
||||
Illegal ->
|
||||
Whoops = "~p is out of bounds (1~65535). Try again...",
|
||||
ok = io:format(Whoops, [Illegal]),
|
||||
create_realm(Realm)
|
||||
end
|
||||
catch error:badarg ->
|
||||
Error = "~tp is not a port number. Try again...",
|
||||
ok = io:format(Error, [S]),
|
||||
create_realm(Realm)
|
||||
end
|
||||
end.
|
||||
|
||||
create_realm(Realm, Prime) ->
|
||||
Instructions =
|
||||
"~n"
|
||||
" Enter a username for the realm sysop.~n"
|
||||
" Valid names can contain only lower-case letters, numbers and the underscore.~n"
|
||||
" Valid names must begin with a lower-case letter.~n",
|
||||
ok = io:format(UserNameMessage),
|
||||
ok = io:format(Instructions),
|
||||
UserName = get_input(),
|
||||
case valid_lower0_9(UserName) of
|
||||
true ->
|
||||
create_realm(Realm, UserName);
|
||||
create_realm(Realm, Prime, UserName);
|
||||
false ->
|
||||
ok = io:format("Bad username ~tp. Try again.~n", [UserName]),
|
||||
create_realm(Realm)
|
||||
create_realm(Realm, Prime)
|
||||
end.
|
||||
|
||||
create_realm(Realm, Prime, UserName) ->
|
||||
Instructions =
|
||||
"~n"
|
||||
" Enter an email address for the realm sysop.~n"
|
||||
" Valid email address rules apply though the checking done here is quite~n"
|
||||
" minimal. Check the address you enter carefully. The only people who will~n"
|
||||
" suffer from an invalid address are your users.~n",
|
||||
ok = io:format(Instructions),
|
||||
Email = get_input(),
|
||||
[User, Host] = string:lexemes(Email, "@"),
|
||||
case {valid_lower0_9(User), valid_label(Host)} of
|
||||
{true, true} ->
|
||||
create_realm(Realm, Prime, UserName, Email);
|
||||
{false, true} ->
|
||||
Message = "The user part of the email address seems invalid. Try again.~n",
|
||||
ok = io:format(Message),
|
||||
create_realm(Realm, Prime, UserName);
|
||||
{true, false} ->
|
||||
Message = "The host part of the email address seems invalid. Try again.~n",
|
||||
ok = io:format(Message),
|
||||
create_realm(Realm, Prime, UserName);
|
||||
{false, false} ->
|
||||
Message = "This email address seems like its totally bonkers. Try again.~n",
|
||||
ok = io:format(Message),
|
||||
create_realm(Realm, Prime, UserName)
|
||||
end.
|
||||
|
||||
|
||||
create_realm(Realm, UserName, UserRecord, Prime, RealmKey, PackageKey) ->
|
||||
create_realm(Realm, Prime, UserName, Email) ->
|
||||
Instructions =
|
||||
"~n"
|
||||
" Enter the real name (or whatever name people will 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 = get_input(),
|
||||
ok = io:format("~nGenerating keys. This might take a while, so settle in...~n"),
|
||||
{ok, RealmKey, RealmPub} = generate_rsa({Realm, Realm ++ ".1.realm"}),
|
||||
{ok, PackageKey, PackagePub} = generate_rsa({Realm, Realm ++ ".1.package"}),
|
||||
{ok, SysopKey, SysopPub} = generate_rsa({Realm, UserName ++ ".1"}),
|
||||
AllKeys = [RealmKey, RealmPub, PackageKey, PackagePub, SysopKey, SysopPub],
|
||||
Copy =
|
||||
fun(From) ->
|
||||
To = filename:basename(From),
|
||||
case filelib:is_file(To) of
|
||||
true ->
|
||||
M = "Whoops! Keyfile local destination ~tp exists! Aborting",
|
||||
ok = log(error, M, [To]),
|
||||
ok = log(info, "Undoing all changes..."),
|
||||
ok = lists:foreach(fun file:delete/1, AllKeys),
|
||||
halt(0);
|
||||
false ->
|
||||
{ok, _} = file:copy(From, To),
|
||||
log(info, "Copying ~tp to the local directory", [From])
|
||||
end
|
||||
end,
|
||||
Drop =
|
||||
fun(File) ->
|
||||
ok = file:delete(File),
|
||||
log(info, "Deleting ~tp", [File])
|
||||
end,
|
||||
DangerousKeys = [PackageKey, SysopKey],
|
||||
ok = lists:foreach(Copy, AllKeys),
|
||||
ok = lists:foreach(Drop, DangerousKeys),
|
||||
Message =
|
||||
"~n"
|
||||
" All of the keys generated have been moved to the current directory.~n"
|
||||
" MAKE AND SECURELY STORE COPIES OF THESE KEYS.~n"
|
||||
" The private package key and private sysop login key have been deleted from the~n"
|
||||
" zomp key directory. These should only exist on your local system, not a prime.~n"
|
||||
" realm server (particularly if other services are run on that machine).~n"
|
||||
" Your package and sysop keys will need to be copied to the ~~/.zomp/keys/~p/~n"
|
||||
" directory on your personal or dev machine.",
|
||||
ok = io:format(Message, [Realm]),
|
||||
Timestamp = calendar:now_to_universal_time(erlang:timestamp()),
|
||||
UserRecord = {{UserName, Realm}, [SysopPub], Email, RealName, 1, Timestamp},
|
||||
RealmMeta =
|
||||
[{realm, Realm},
|
||||
{prime, Prime},
|
||||
{realm_keys, [RealmKey],
|
||||
{package_keys, [PacakageKey]
|
||||
{revision, 0},
|
||||
{serial, 0},
|
||||
{mirrors, []}],
|
||||
ok = log(info, "Seriously, we would be creating a realm now."),
|
||||
{prime, Prime},
|
||||
{private, []},
|
||||
{mirrors, []},
|
||||
{sysops, [UserRecord]},
|
||||
{realm_keys, [RealmPub]},
|
||||
{package_keys, [PackagePub]}],
|
||||
ok = log(info, "Would be writing ~tp", [RealmMeta]),
|
||||
halt(0).
|
||||
|
||||
|
||||
@ -1961,7 +2077,33 @@ hurr() -> io:format("That isn't an option.~n").
|
||||
|
||||
|
||||
|
||||
%%% Directory Management
|
||||
%%% Directory & File Management
|
||||
|
||||
%-spec move_file(From, To) -> Result
|
||||
% when From :: file:filename(),
|
||||
% To :: file:filename(),
|
||||
% Result :: ok
|
||||
% | {error, Reason},
|
||||
% Reason :: bad_source
|
||||
% | destination_exists
|
||||
% | file:posix().
|
||||
%%% @private
|
||||
%%% Utility function to safely copy a file From one path To another without clobbering the
|
||||
%%% destination in the event it already exists. Both the source and the destination must be
|
||||
%%% complete filenames, not directories.
|
||||
%
|
||||
%move_file(From, To) ->
|
||||
% case {filelib:is_regular(From), filelib:is_file(To)} of
|
||||
% {false, false} ->
|
||||
% case file:copy(From, To) of
|
||||
% {ok, _} -> file:delete(From);
|
||||
% Error -> Error
|
||||
% end;
|
||||
% {true, _} ->
|
||||
% {error, bad_source};
|
||||
% {false, true} ->
|
||||
% {error, destination_exists}
|
||||
% end.
|
||||
|
||||
|
||||
-spec ensure_zomp_home() -> ok.
|
||||
@ -2248,4 +2390,4 @@ log(Level, Format, Args) ->
|
||||
warning -> "[WARNING]";
|
||||
error -> "[ERROR]"
|
||||
end,
|
||||
io:format("~s ~p: " ++ Format ++ "~n", [Tag, self() | Args]).
|
||||
io:format("~p ~s: " ++ Format ++ "~n", [self(), Tag | Args]).
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user