Current section

Files

Jump to
mad src mad_ca.erl
Raw

src/mad_ca.erl

-module(mad_ca).
-include_lib("public_key/include/public_key.hrl").
-compile(export_all).
host() -> "ca.n2o.dev:8046".
cat(X) -> lists:concat(X).
replace(S,A,B) -> re:replace(S,A,B,[global,{return,binary}]).
u(X) -> string:to_upper(X).
root(Crypto) -> {cat(["cert/",Crypto,"/"]),"synrc.cnf"}.
rsa(X) -> cmd("rsa",X).
ecc(X) -> cmd("ecc",X).
cmd(C,[]) -> boot(C), {ok,C};
cmd(C,["ca"]) -> boot(C), up(C), {ok,C};
cmd(C,[T|N]) -> boot(C), enroll(C,T,N), {ok,C};
cmd(C,_) -> boot(C), {ok,C}.
boot(Crypto) ->
{Dir,CNF} = root(Crypto),
case file:read_file_info(Dir++CNF) of
{ok,_} -> skip;
{error,_} -> {Dir,CNF} = root(Crypto), filelib:ensure_dir(Dir),
file:write_file(Dir++CNF,replace(replace(cnf(),"PATH",mad_utils:cwd()),"CRYPTO",Crypto)),
up(Crypto) end, {ok,Crypto}.
up(Crypto) ->
application:start(inets),
URI = cat(["http://",host(),"/up/",Crypto]),
{ok,{{"HTTP/1.1",200,"OK"},_,Cert}} = httpc:request(post,{URI,[],[],<<"">>},[],[]),
PEM = list_to_binary(Cert),
ok = file:write_file(cat(["cert/",Crypto,"/caroot.pem"]),PEM),
dump(PEM,"CA").
enroll(Crypto,Type,Name) when (Type == "server" orelse Type == "client" orelse Type == "ocsp")
andalso (Crypto == "rsa" orelse Crypto == "ecc") ->
Pass = application:get_env(ca,passin,"pass:0"),
application:start(inets),
Y = string:join(Name," "),
ok = key(Crypto,Pass,Y),
{ok, F} = file:read_file(cat(["cert/",Crypto,"/",Y,".csr"])),
URI = cat(["http://",host(),"/enroll/",Crypto,"/",Type]),
{ok,{{"HTTP/1.1",200,"OK"},_,Cert}} = httpc:request(post,{URI,[],"multipart/form-data",F},[],[]),
PEM = list_to_binary(Cert),
ok = file:write_file(cat(["cert/",Crypto,"/",Y,".pem"]),PEM),
dump(PEM,Y).
dump(PEM,Y) ->
{_,{_,D,_}} = lists:keysearch('Certificate',1,public_key:pem_decode(PEM)),
OTPCert = public_key:pkix_decode_cert(D,otp),
PKIInfo = OTPCert#'OTPCertificate'.tbsCertificate#'OTPTBSCertificate'.subjectPublicKeyInfo,
io:format("CERT: ~s KEY: ~p~n",[Y,PKIInfo]).
key("rsa",_,X) ->
{done,0,_} = sh:run("openssl genrsa -out \"cert/rsa/"++ X ++ ".key\" 2048"),
{done,0,_} = sh:run("openssl req -new -days 365 -key \"cert/rsa/"++ X ++".key\" -out \"cert/rsa/"++ X ++".csr\" "
" -subj \"/C=UA/ST=Kyiv/O=SYNRC/CN="++ X ++ "\""), ok;
key("ecc",Pass,X) ->
Pass = application:get_env(ca,passin,"pass:0"),
{done,0,_} = sh:run("openssl ecparam -name secp384r1 -out \"cert/ecc/"++X++".ecp\""),
{done,0,_} = sh:run("cp \"cert/ecc/"++X++".ecp\" key"),
{done,0,_} = sh:run("openssl req -config cert/ecc/synrc.cnf -passout " ++ Pass ++
" -new -newkey ec:key -keyout \"cert/ecc/"++X++".key.enc\" -out \"cert/ecc/"++X++".csr\""
" -subj \"/C=UA/ST=Kyiv/O=SYNRC/CN="++X++"\""),
{done,0,_} = sh:run("rm key"),
{done,0,_} = sh:run("openssl ec -in \"cert/ecc/"++X++".key.enc\" -out \"cert/ecc/"++X++".key\" -passin "++Pass),
ok.
cnf() ->
mad_repl:load(),
try lists:flatten(
[case string:str(File,"priv/cnf") of 1 -> Bin; _ -> []
end || {File,Bin} <- ets:tab2list(filesystem), is_list(File)])
catch _:_ -> [] end.