diff --git a/README.md b/README.md index 65db7f1..c66406b 100644 --- a/README.md +++ b/README.md @@ -107,18 +107,19 @@ of Erlang property list. *Configuration variables* -| Variable name | Expected values | Apache equivalent | Definition ------------------------|------------------------------------|-----------------------|-------------------------------------------- -| `dev_mode` | `true`, `false` | None | Enables TCP access without TLS. -| `tls_port` | `700` | Listen | At which port should we open a TLS socket. Default is 700. -| `tcp_port` | `70000` | Listen | At which port should we open a TCP socket. Only in `dev_mode`. -| `epp_session_url` | `https://example.com/epp/session` | EppSessionRoot | HTTP address of the session endpoints including schema and port. -| `epp_command_url` | `https://example.com/epp/command` | EppCommandRoot | HTTP address of the command endpoints including schema and port. -| `epp_error_url` | `https://example.com/epp/error` | EppErrorRoot | HTTP address of the error endpoints including schema and port. -| `cacertfile_path` | `/opt/ca/ca.crt.pem` | SSLCACertificateFile | Where is the client root CA located. Can be inside apps/epp_proxy/priv or absolute path. -| `certfile_path` | `/opt/ca/server.crt.pem` | SSLCertificateFile | Where is the server certificate located. Can be inside apps/epp_proxy/priv or absolute path. -| `keyfile_path` | `/opt/ca/server.key.pem` | SSLCertificateKeyFile | Where is the server key located. Can be inside apps/epp_proxy/priv or absolute path. -| `crlfile_path` | `/opt/ca/crl.pem` | SSLCARevocationFile | Where is the CRL file located. Can be inside apps/epp_proxy/priv or absolute path. When not set, not CRL check is performed. +| Variable name | Expected values | Apache equivalent | Definition +-------------------------|------------------------------------|-----------------------|-------------------------------------------- +| `dev_mode` | `true`, `false` | None | Enables TCP access without TLS. +| `tls_port` | `700` | Listen | At which port should we open a TLS socket. Default is 700. +| `tcp_port` | `70000` | Listen | At which port should we open a TCP socket. Only in `dev_mode`. +| `epp_session_url` | `https://example.com/epp/session` | EppSessionRoot | HTTP address of the session endpoints including schema and port. +| `epp_command_url` | `https://example.com/epp/command` | EppCommandRoot | HTTP address of the command endpoints including schema and port. +| `epp_error_url` | `https://example.com/epp/error` | EppErrorRoot | HTTP address of the error endpoints including schema and port. +| `require_client_certs` | `true`, `false` | None | Enables TLS connections with required or optional client certificates. Provided optional client certificates are still being verified. +| `cacertfile_path` | `/opt/ca/ca.crt.pem` | SSLCACertificateFile | Where is the client root CA located. Can be inside apps/epp_proxy/priv or absolute path. +| `certfile_path` | `/opt/ca/server.crt.pem` | SSLCertificateFile | Where is the server certificate located. Can be inside apps/epp_proxy/priv or absolute path. +| `keyfile_path` | `/opt/ca/server.key.pem` | SSLCertificateKeyFile | Where is the server key located. Can be inside apps/epp_proxy/priv or absolute path. +| `crlfile_path` | `/opt/ca/crl.pem` | SSLCARevocationFile | Where is the CRL file located. Can be inside apps/epp_proxy/priv or absolute path. When not set, not CRL check is performed. Migrating from mod_epp diff --git a/apps/epp_proxy/src/epp_tls_worker.erl b/apps/epp_proxy/src/epp_tls_worker.erl index 1941251..a8bf673 100644 --- a/apps/epp_proxy/src/epp_tls_worker.erl +++ b/apps/epp_proxy/src/epp_tls_worker.erl @@ -169,20 +169,33 @@ log_opened_connection(Ip) -> "~p.~n", [ReadableIp, self()]). +require_client_certs() -> + case application:get_env(epp_proxy, require_client_certs) of + {ok, false} -> false; + {ok, true} -> true; + _ -> true + end. + %% Extract state info from socket. Fail if you must. state_from_socket(Socket, State) -> - {ok, PeerCert} = ssl:peercert(Socket), {ok, {PeerIp, _PeerPort}} = ssl:peername(Socket), - {SSL_CLIENT_S_DN_CN, SSL_CLIENT_CERT} = - epp_certs:headers_from_cert(PeerCert), - Headers = [{"SSL-CLIENT-CERT", SSL_CLIENT_CERT}, - {"SSL-CLIENT-S-DN-CN", SSL_CLIENT_S_DN_CN}, - {"User-Agent", <<"EPP proxy">>}, - {"X-Forwarded-for", epp_util:readable_ip(PeerIp)}], + PlainHeaders = [ + {"User-Agent", <<"EPP proxy">>}, + {"X-Forwarded-for", epp_util:readable_ip(PeerIp)}], + case {ssl:peercert(Socket), require_client_certs()} of + {{error, no_peercert}, false} -> Headers = PlainHeaders; + % {{error, no_peercert}, true} -> ; %% TODO: maybe send the reason of connection close + {{ok, PeerCert}, _} -> + {SSL_CLIENT_S_DN_CN, SSL_CLIENT_CERT} = + epp_certs:headers_from_cert(PeerCert), + Headers = lists:append(PlainHeaders, [ + {"SSL-CLIENT-CERT", SSL_CLIENT_CERT}, + {"SSL-CLIENT-S-DN-CN", SSL_CLIENT_S_DN_CN}]) + end, NewState = State#state{socket = Socket, - headers = Headers}, + headers = Headers}, lager:info("Established connection with: [~p]~n", - [NewState]), + [NewState]), NewState. %% Get status, XML record, command and clTRID if defined. diff --git a/config/sys.config b/config/sys.config index c2f3ae4..f11d43b 100644 --- a/config/sys.config +++ b/config/sys.config @@ -17,6 +17,8 @@ {epp_session_url, "https://registry.test/epp/session/"}, {epp_command_url, "https://registry.test/epp/command/"}, {epp_error_url, "https://registry.test/epp/error/"}, + %% Allows client to connect to epp_proxy without client certificate using TLS + {require_client_certs, true}, %% Path to root CA that should check the client certificates. {cacertfile_path, "/opt/shared/ca/certs/ca.crt.pem"}, %% Path to server's certficate file.