wip
This commit is contained in:
parent
5d7d6599a9
commit
cc4d55288d
188
zx
188
zx
@ -668,7 +668,7 @@ package(TargetDir) ->
|
|||||||
[] ->
|
[] ->
|
||||||
ok = log(info, "Need to generate key"),
|
ok = log(info, "Need to generate key"),
|
||||||
KeyID = prompt_keygen(),
|
KeyID = prompt_keygen(),
|
||||||
ok = generate_rsa(KeyID),
|
{ok, _, _} = generate_rsa(KeyID),
|
||||||
package(KeyID, TargetDir);
|
package(KeyID, TargetDir);
|
||||||
[KeyName] ->
|
[KeyName] ->
|
||||||
KeyID = {Realm, KeyName},
|
KeyID = {Realm, KeyName},
|
||||||
@ -1144,11 +1144,14 @@ prompt_keygen() ->
|
|||||||
case {valid_lower0_9(Realm), valid_label(KeyName)} of
|
case {valid_lower0_9(Realm), valid_label(KeyName)} of
|
||||||
{true, true} ->
|
{true, true} ->
|
||||||
{Realm, KeyName};
|
{Realm, KeyName};
|
||||||
{false, _} ->
|
{false, true} ->
|
||||||
ok = io:format("Bad realm name ~tp. Try again.~n", [Realm]),
|
ok = io:format("Bad realm name ~tp. Try again.~n", [Realm]),
|
||||||
prompt_keygen();
|
prompt_keygen();
|
||||||
{true, false} ->
|
{true, false} ->
|
||||||
ok = io:format("Bad key name ~tp. Try again.~n", [KeyName]),
|
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()
|
prompt_keygen()
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -1161,8 +1164,8 @@ create_keypair() ->
|
|||||||
ok = file:set_cwd(zomp_dir()),
|
ok = file:set_cwd(zomp_dir()),
|
||||||
KeyID = prompt_keygen(),
|
KeyID = prompt_keygen(),
|
||||||
case generate_rsa(KeyID) of
|
case generate_rsa(KeyID) of
|
||||||
ok -> halt(0);
|
{ok, _, _} -> halt(0);
|
||||||
Error -> error_exit("create_keypair/0 failed with ~tp", [Error], ?FILE, ?LINE)
|
Error -> error_exit("create_keypair/0 failed with ~tp", [Error], ?FILE, ?LINE)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
@ -1198,7 +1201,7 @@ generate_rsa({Realm, KeyName}) ->
|
|||||||
ok = log(info, "~ts and ~ts agree", [KeyFile, PubFile]),
|
ok = log(info, "~ts and ~ts agree", [KeyFile, PubFile]),
|
||||||
ok = log(info, "Wrote private key to: ~ts.", [KeyFile]),
|
ok = log(info, "Wrote private key to: ~ts.", [KeyFile]),
|
||||||
ok = log(info, "Wrote public key to: ~ts.", [PubFile]),
|
ok = log(info, "Wrote public key to: ~ts.", [PubFile]),
|
||||||
ok;
|
{ok, KeyFile, PubFile};
|
||||||
false ->
|
false ->
|
||||||
ok = lists:foreach(fun file:delete/1, [PemFile, KeyFile, PubFile]),
|
ok = lists:foreach(fun file:delete/1, [PemFile, KeyFile, PubFile]),
|
||||||
ok = log(error, "Something has gone wrong."),
|
ok = log(error, "Something has gone wrong."),
|
||||||
@ -1400,11 +1403,12 @@ dialyze() ->
|
|||||||
%%% Create Realm & Sysop
|
%%% Create Realm & Sysop
|
||||||
|
|
||||||
create_realm() ->
|
create_realm() ->
|
||||||
RealmMessage =
|
Instructions =
|
||||||
"~n Enter a name for your new realm.~n"
|
"~n"
|
||||||
|
" Enter a name for your new realm.~n"
|
||||||
" Valid names can contain only lower-case letters, numbers and the underscore.~n"
|
" Valid names can contain only lower-case letters, numbers and the underscore.~n"
|
||||||
" Valid names must begin with a lower-case letter.~n",
|
" Valid names must begin with a lower-case letter.~n",
|
||||||
ok = io:format(RealmMessage),
|
ok = io:format(Instructions),
|
||||||
Realm = get_input(),
|
Realm = get_input(),
|
||||||
case valid_lower0_9(Realm) of
|
case valid_lower0_9(Realm) of
|
||||||
true ->
|
true ->
|
||||||
@ -1422,32 +1426,144 @@ create_realm() ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
create_realm(Realm) ->
|
create_realm(Realm) ->
|
||||||
UserNameMessage =
|
HostInstructions =
|
||||||
"~n Enter a username for the realm sysop.~n"
|
"~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 can contain only lower-case letters, numbers and the underscore.~n"
|
||||||
" Valid names must begin with a lower-case letter.~n",
|
" Valid names must begin with a lower-case letter.~n",
|
||||||
ok = io:format(UserNameMessage),
|
ok = io:format(Instructions),
|
||||||
UserName = get_input(),
|
UserName = get_input(),
|
||||||
case valid_lower0_9(UserName) of
|
case valid_lower0_9(UserName) of
|
||||||
true ->
|
true ->
|
||||||
create_realm(Realm, UserName);
|
create_realm(Realm, Prime, UserName);
|
||||||
false ->
|
false ->
|
||||||
ok = io:format("Bad username ~tp. Try again.~n", [UserName]),
|
ok = io:format("Bad username ~tp. Try again.~n", [UserName]),
|
||||||
create_realm(Realm)
|
create_realm(Realm, Prime)
|
||||||
end.
|
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, Prime, UserName, Email) ->
|
||||||
create_realm(Realm, UserName, UserRecord, Prime, RealmKey, PackageKey) ->
|
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 =
|
RealmMeta =
|
||||||
[{realm, Realm},
|
[{realm, Realm},
|
||||||
{prime, Prime},
|
|
||||||
{realm_keys, [RealmKey],
|
|
||||||
{package_keys, [PacakageKey]
|
|
||||||
{revision, 0},
|
{revision, 0},
|
||||||
{serial, 0},
|
{prime, Prime},
|
||||||
{mirrors, []}],
|
{private, []},
|
||||||
ok = log(info, "Seriously, we would be creating a realm now."),
|
{mirrors, []},
|
||||||
|
{sysops, [UserRecord]},
|
||||||
|
{realm_keys, [RealmPub]},
|
||||||
|
{package_keys, [PackagePub]}],
|
||||||
|
ok = log(info, "Would be writing ~tp", [RealmMeta]),
|
||||||
halt(0).
|
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.
|
-spec ensure_zomp_home() -> ok.
|
||||||
@ -2248,4 +2390,4 @@ log(Level, Format, Args) ->
|
|||||||
warning -> "[WARNING]";
|
warning -> "[WARNING]";
|
||||||
error -> "[ERROR]"
|
error -> "[ERROR]"
|
||||||
end,
|
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