aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl/examples
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/ssl/examples
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/ssl/examples')
-rw-r--r--lib/ssl/examples/certs/Makefile24
-rw-r--r--lib/ssl/examples/certs/Makefile.in80
-rw-r--r--lib/ssl/examples/certs/ebin/.gitignore0
-rw-r--r--lib/ssl/examples/certs/rnd/RANDbin0 -> 512 bytes
-rw-r--r--lib/ssl/examples/certs/src/make_certs.erl261
-rw-r--r--lib/ssl/examples/ebin/.gitignore0
-rw-r--r--lib/ssl/examples/src/Makefile78
-rw-r--r--lib/ssl/examples/src/client_server.erl85
8 files changed, 528 insertions, 0 deletions
diff --git a/lib/ssl/examples/certs/Makefile b/lib/ssl/examples/certs/Makefile
new file mode 100644
index 0000000000..121fcc6950
--- /dev/null
+++ b/lib/ssl/examples/certs/Makefile
@@ -0,0 +1,24 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2003-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+#
+# Invoke with GNU make or clearmake -C gnu.
+#
+
+include $(ERL_TOP)/make/run_make.mk
diff --git a/lib/ssl/examples/certs/Makefile.in b/lib/ssl/examples/certs/Makefile.in
new file mode 100644
index 0000000000..4ea7aaf6dc
--- /dev/null
+++ b/lib/ssl/examples/certs/Makefile.in
@@ -0,0 +1,80 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2003-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+#
+
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+include ../../vsn.mk
+VSN=$(SSL_VSN)
+
+RELSYSDIR = $(RELEASE_PATH)/lib/ssl-$(VSN)
+
+EBIN = ebin
+ETC = etc
+SRC = src
+
+OPENSSL_CMD = @OPENSSL_CMD@
+
+# We are generating more files than in the following list, but we take
+# there existence as successful execution of make rules
+
+PEMS = cacerts.pem cert.pem key.pem
+
+PEMFILES = $(PEMS:%=$(ETC)/client/%) $(PEMS:%=$(ETC)/server/%)
+
+debug opt: $(PEMFILES)
+
+$(PEMFILES): done
+
+done: $(EBIN)/make_certs.beam
+ erl -noinput -pa $(EBIN) -run make_certs all $(OPENSSL_CMD) \
+ -s erlang halt
+ echo >done
+
+$(EBIN)/make_certs.beam: $(SRC)/make_certs.erl
+ cd src; erlc -W -o ../$(EBIN) make_certs.erl
+
+clean:
+ rm -fr $(EBIN)/* $(SRC)/*~ $(SRC)/*.beam $(ETC) done \
+ stderr.txt erl_crash.dump *~
+
+docs:
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/examples/certs
+ tar cf - Makefile ebin etc rnd src | \
+ (cd $(RELSYSDIR)/examples/certs; tar xf -)
+ chmod -f -R ug+rw $(RELSYSDIR)/examples
+
+release_docs_spec:
+
+
+
+
+
+
+
+
diff --git a/lib/ssl/examples/certs/ebin/.gitignore b/lib/ssl/examples/certs/ebin/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/ssl/examples/certs/ebin/.gitignore
diff --git a/lib/ssl/examples/certs/rnd/RAND b/lib/ssl/examples/certs/rnd/RAND
new file mode 100644
index 0000000000..70997bd01f
--- /dev/null
+++ b/lib/ssl/examples/certs/rnd/RAND
Binary files differ
diff --git a/lib/ssl/examples/certs/src/make_certs.erl b/lib/ssl/examples/certs/src/make_certs.erl
new file mode 100644
index 0000000000..c374836568
--- /dev/null
+++ b/lib/ssl/examples/certs/src/make_certs.erl
@@ -0,0 +1,261 @@
+%% The purpose of this module is to create example certificates for
+%% testing.
+%% Run it as:
+%%
+%% erl -noinput -run make_certs all "/path/to/openssl" -s erlang halt
+%%
+
+-module(make_certs).
+-export([all/0, all/1]).
+
+-record(dn, {commonName,
+ organizationalUnitName = "Erlang OTP",
+ organizationName = "Ericsson AB",
+ localityName = "Stockholm",
+ countryName = "SE",
+ emailAddress = "[email protected]"}).
+
+all() ->
+ all(["openssl"]).
+
+all([OpenSSLCmd]) ->
+ Root = filename:dirname(filename:dirname((code:which(?MODULE)))),
+ %% io:fwrite("Root : ~s~n", [Root]),
+ NRoot = filename:join([Root, "etc"]),
+ file:make_dir(NRoot),
+ create_rnd(Root, "etc"), % For all requests
+ rootCA(NRoot, OpenSSLCmd, "erlangCA"),
+ intermediateCA(NRoot, OpenSSLCmd, "otpCA", "erlangCA"),
+ endusers(NRoot, OpenSSLCmd, "otpCA", ["client", "server"]),
+ collect_certs(NRoot, ["erlangCA", "otpCA"], ["client", "server"]),
+ remove_rnd(Root, "etc").
+
+rootCA(Root, OpenSSLCmd, Name) ->
+ create_ca_dir(Root, Name, ca_cnf(Name)),
+ DN = #dn{commonName = Name},
+ create_self_signed_cert(Root, OpenSSLCmd, Name, req_cnf(DN)),
+ ok.
+
+intermediateCA(Root, OpenSSLCmd, CA, ParentCA) ->
+ CA = "otpCA",
+ create_ca_dir(Root, CA, ca_cnf(CA)),
+ CARoot = filename:join([Root, CA]),
+ DN = #dn{commonName = CA},
+ CnfFile = filename:join([CARoot, "req.cnf"]),
+ file:write_file(CnfFile, req_cnf(DN)),
+ KeyFile = filename:join([CARoot, "private", "key.pem"]),
+ ReqFile = filename:join([CARoot, "req.pem"]),
+ create_req(Root, OpenSSLCmd, CnfFile, KeyFile, ReqFile),
+ CertFile = filename:join([CARoot, "cert.pem"]),
+ sign_req(Root, OpenSSLCmd, ParentCA, "ca_cert", ReqFile, CertFile).
+
+endusers(Root, OpenSSLCmd, CA, Users) ->
+ lists:foreach(fun(User) -> enduser(Root, OpenSSLCmd, CA, User) end, Users).
+
+enduser(Root, OpenSSLCmd, CA, User) ->
+ UsrRoot = filename:join([Root, User]),
+ file:make_dir(UsrRoot),
+ CnfFile = filename:join([UsrRoot, "req.cnf"]),
+ DN = #dn{commonName = User},
+ file:write_file(CnfFile, req_cnf(DN)),
+ KeyFile = filename:join([UsrRoot, "key.pem"]),
+ ReqFile = filename:join([UsrRoot, "req.pem"]),
+ create_req(Root, OpenSSLCmd, CnfFile, KeyFile, ReqFile),
+ CertFile = filename:join([UsrRoot, "cert.pem"]),
+ sign_req(Root, OpenSSLCmd, CA, "user_cert", ReqFile, CertFile).
+
+collect_certs(Root, CAs, Users) ->
+ Bins = lists:foldr(
+ fun(CA, Acc) ->
+ File = filename:join([Root, CA, "cert.pem"]),
+ {ok, Bin} = file:read_file(File),
+ [Bin, "\n" | Acc]
+ end, [], CAs),
+ lists:foreach(
+ fun(User) ->
+ File = filename:join([Root, User, "cacerts.pem"]),
+ file:write_file(File, Bins)
+ end, Users).
+
+create_self_signed_cert(Root, OpenSSLCmd, CAName, Cnf) ->
+ CARoot = filename:join([Root, CAName]),
+ CnfFile = filename:join([CARoot, "req.cnf"]),
+ file:write_file(CnfFile, Cnf),
+ KeyFile = filename:join([CARoot, "private", "key.pem"]),
+ CertFile = filename:join([CARoot, "cert.pem"]),
+ Cmd = [OpenSSLCmd, " req"
+ " -new"
+ " -x509"
+ " -config ", CnfFile,
+ " -keyout ", KeyFile,
+ " -out ", CertFile],
+ Env = [{"ROOTDIR", Root}],
+ cmd(Cmd, Env).
+
+create_ca_dir(Root, CAName, Cnf) ->
+ CARoot = filename:join([Root, CAName]),
+ file:make_dir(CARoot),
+ create_dirs(CARoot, ["certs", "crl", "newcerts", "private"]),
+ create_rnd(Root, filename:join([CAName, "private"])),
+ create_files(CARoot, [{"serial", "01\n"},
+ {"index.txt", ""},
+ {"ca.cnf", Cnf}]).
+
+create_req(Root, OpenSSLCmd, CnfFile, KeyFile, ReqFile) ->
+ Cmd = [OpenSSLCmd, " req"
+ " -new"
+ " -config ", CnfFile,
+ " -keyout ", KeyFile,
+ " -out ", ReqFile],
+ Env = [{"ROOTDIR", Root}],
+ cmd(Cmd, Env).
+
+sign_req(Root, OpenSSLCmd, CA, CertType, ReqFile, CertFile) ->
+ CACnfFile = filename:join([Root, CA, "ca.cnf"]),
+ Cmd = [OpenSSLCmd, " ca"
+ " -batch"
+ " -notext"
+ " -config ", CACnfFile,
+ " -extensions ", CertType,
+ " -in ", ReqFile,
+ " -out ", CertFile],
+ Env = [{"ROOTDIR", Root}],
+ cmd(Cmd, Env).
+
+%%
+%% Misc
+%%
+
+create_dirs(Root, Dirs) ->
+ lists:foreach(fun(Dir) ->
+ file:make_dir(filename:join([Root, Dir])) end,
+ Dirs).
+
+create_files(Root, NameContents) ->
+ lists:foreach(
+ fun({Name, Contents}) ->
+ file:write_file(filename:join([Root, Name]), Contents) end,
+ NameContents).
+
+create_rnd(Root, Dir) ->
+ From = filename:join([Root, "rnd", "RAND"]),
+ To = filename:join([Root, Dir, "RAND"]),
+ file:copy(From, To).
+
+remove_rnd(Root, Dir) ->
+ File = filename:join([Root, Dir, "RAND"]),
+ file:delete(File).
+
+cmd(Cmd, Env) ->
+ FCmd = lists:flatten(Cmd),
+ Port = open_port({spawn, FCmd}, [stream, eof, exit_status,
+ {env, Env}]),
+ eval_cmd(Port).
+
+eval_cmd(Port) ->
+ receive
+ {Port, {data, _}} ->
+ eval_cmd(Port);
+ {Port, eof} ->
+ ok
+ end,
+ receive
+ {Port, {exit_status, Status}} when Status /= 0 ->
+ %% io:fwrite("exit status: ~w~n", [Status]),
+ erlang:halt(Status)
+ after 0 ->
+ ok
+ end.
+
+%%
+%% Contents of configuration files
+%%
+
+req_cnf(DN) ->
+ ["# Purpose: Configuration for requests (end users and CAs)."
+ "\n"
+ "ROOTDIR = $ENV::ROOTDIR\n"
+ "\n"
+
+ "[req]\n"
+ "input_password = secret\n"
+ "output_password = secret\n"
+ "default_bits = 1024\n"
+ "RANDFILE = $ROOTDIR/RAND\n"
+ "encrypt_key = no\n"
+ "default_md = sha1\n"
+ "#string_mask = pkix\n"
+ "x509_extensions = ca_ext\n"
+ "prompt = no\n"
+ "distinguished_name= name\n"
+ "\n"
+
+ "[name]\n"
+ "commonName = ", DN#dn.commonName, "\n"
+ "organizationalUnitName = ", DN#dn.organizationalUnitName, "\n"
+ "organizationName = ", DN#dn.organizationName, "\n"
+ "localityName = ", DN#dn.localityName, "\n"
+ "countryName = ", DN#dn.countryName, "\n"
+ "emailAddress = ", DN#dn.emailAddress, "\n"
+ "\n"
+
+ "[ca_ext]\n"
+ "basicConstraints = critical, CA:true\n"
+ "keyUsage = cRLSign, keyCertSign\n"
+ "subjectKeyIdentifier = hash\n"
+ "subjectAltName = email:copy\n"].
+
+
+ca_cnf(CA) ->
+ ["# Purpose: Configuration for CAs.\n"
+ "\n"
+ "ROOTDIR = $ENV::ROOTDIR\n"
+ "default_ca = ca\n"
+ "\n"
+
+ "[ca]\n"
+ "dir = $ROOTDIR/", CA, "\n"
+ "certs = $dir/certs\n"
+ "crl_dir = $dir/crl\n"
+ "database = $dir/index.txt\n"
+ "new_certs_dir = $dir/newcerts\n"
+ "certificate = $dir/cert.pem\n"
+ "serial = $dir/serial\n"
+ "crl = $dir/crl.pem\n"
+ "private_key = $dir/private/key.pem\n"
+ "RANDFILE = $dir/private/RAND\n"
+ "\n"
+ "x509_extensions = user_cert\n"
+ "default_days = 3600\n"
+ "default_md = sha1\n"
+ "preserve = no\n"
+ "policy = policy_match\n"
+ "\n"
+
+ "[policy_match]\n"
+ "commonName = supplied\n"
+ "organizationalUnitName = optional\n"
+ "organizationName = match\n"
+ "countryName = match\n"
+ "localityName = match\n"
+ "emailAddress = supplied\n"
+ "\n"
+
+ "[user_cert]\n"
+ "basicConstraints = CA:false\n"
+ "keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n"
+ "subjectKeyIdentifier = hash\n"
+ "authorityKeyIdentifier = keyid,issuer:always\n"
+ "subjectAltName = email:copy\n"
+ "issuerAltName = issuer:copy\n"
+ "\n"
+
+ "[ca_cert]\n"
+ "basicConstraints = critical,CA:true\n"
+ "keyUsage = cRLSign, keyCertSign\n"
+ "subjectKeyIdentifier = hash\n"
+ "authorityKeyIdentifier = keyid:always,issuer:always\n"
+ "subjectAltName = email:copy\n"
+ "issuerAltName = issuer:copy\n"].
+
+
diff --git a/lib/ssl/examples/ebin/.gitignore b/lib/ssl/examples/ebin/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/ssl/examples/ebin/.gitignore
diff --git a/lib/ssl/examples/src/Makefile b/lib/ssl/examples/src/Makefile
new file mode 100644
index 0000000000..46c0507b3a
--- /dev/null
+++ b/lib/ssl/examples/src/Makefile
@@ -0,0 +1,78 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2003-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+#
+
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../../vsn.mk
+VSN=$(SSL_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/ssl-$(VSN)
+
+# ----------------------------------------------------
+# Common Macros
+# ----------------------------------------------------
+EXTRA_ERLC_FLAGS = +warn_unused_vars
+ERL_COMPILE_FLAGS += $(EXTRA_ERLC_FLAGS)
+
+
+MODULES = client_server
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+debug opt: $(TARGET_FILES)
+
+clean:
+ rm -fr $(TARGET_FILES) *~ *.beam
+
+docs:
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/examples/src
+ $(INSTALL_DIR) $(RELSYSDIR)/examples/ebin
+ (cd ..; tar cf - src ebin | (cd $(RELSYSDIR)/examples; tar xf -))
+ chmod -f -R ug+w $(RELSYSDIR)/examples
+
+release_docs_spec:
+
+
+
+
+
+
+
diff --git a/lib/ssl/examples/src/client_server.erl b/lib/ssl/examples/src/client_server.erl
new file mode 100644
index 0000000000..baf5a9185e
--- /dev/null
+++ b/lib/ssl/examples/src/client_server.erl
@@ -0,0 +1,85 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%% Purpose: Example of SSL client and server using example certificates.
+
+-module(client_server).
+
+-export([start/0, start/1, init_connect/1]).
+
+start() ->
+ start([ssl, subject]).
+
+start(CertOpts) ->
+ %% Start ssl application
+ application:start(ssl),
+
+ %% Always seed
+ ssl:seed("ellynatefttidppohjeh"),
+
+ %% Let the current process be the server that listens and accepts
+ %% Listen
+ {ok, LSock} = ssl:listen(0, mk_opts(listen)),
+ {ok, {_, LPort}} = ssl:sockname(LSock),
+ io:fwrite("Listen: port = ~w.~n", [LPort]),
+
+ %% Spawn the client process that connects to the server
+ spawn(?MODULE, init_connect, [{LPort, CertOpts}]),
+
+ %% Accept
+ {ok, ASock} = ssl:transport_accept(LSock),
+ ok = ssl:ssl_accept(ASock),
+ io:fwrite("Accept: accepted.~n"),
+ {ok, Cert} = ssl:peercert(ASock, CertOpts),
+ io:fwrite("Accept: peer cert:~n~p~n", [Cert]),
+ io:fwrite("Accept: sending \"hello\".~n"),
+ ssl:send(ASock, "hello"),
+ {error, closed} = ssl:recv(ASock, 0),
+ io:fwrite("Accept: detected closed.~n"),
+ ssl:close(ASock),
+ io:fwrite("Listen: closing and terminating.~n"),
+ ssl:close(LSock),
+ application:stop(ssl).
+
+
+%% Client connect
+init_connect({LPort, CertOpts}) ->
+ {ok, Host} = inet:gethostname(),
+ {ok, CSock} = ssl:connect(Host, LPort, mk_opts(connect)),
+ io:fwrite("Connect: connected.~n"),
+ {ok, Cert} = ssl:peercert(CSock, CertOpts),
+ io:fwrite("Connect: peer cert:~n~p~n", [Cert]),
+ {ok, Data} = ssl:recv(CSock, 0),
+ io:fwrite("Connect: got data: ~p~n", [Data]),
+ io:fwrite("Connect: closing and terminating.~n"),
+ ssl:close(CSock).
+
+mk_opts(listen) ->
+ mk_opts("server");
+mk_opts(connect) ->
+ mk_opts("client");
+mk_opts(Role) ->
+ Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
+ [{active, false},
+ {verify, 2},
+ {depth, 2},
+ {cacertfile, filename:join([Dir, Role, "cacerts.pem"])},
+ {certfile, filename:join([Dir, Role, "cert.pem"])},
+ {keyfile, filename:join([Dir, Role, "key.pem"])}].
+