File 0199-ftp-support-TLS-for-start_-standalone-server.patch of Package erlang

From 0e7f9415c92d96d45060844556c414514791e715 Mon Sep 17 00:00:00 2001
From: Alexander Clouter <alex@digriz.org.uk>
Date: Thu, 28 May 2020 16:15:39 +0100
Subject: [PATCH 09/14] ftp: support TLS for start_{standalone,server}

---
 lib/ftp/src/ftp.erl | 80 ++++++++++++++-------------------------------
 1 file changed, 24 insertions(+), 56 deletions(-)

diff --git a/lib/ftp/src/ftp.erl b/lib/ftp/src/ftp.erl
index b2eb7c6a13..f3860f503d 100644
--- a/lib/ftp/src/ftp.erl
+++ b/lib/ftp/src/ftp.erl
@@ -137,11 +137,9 @@ start() ->
 start_standalone(Options) ->
     try
         {ok, StartOptions} = start_options(Options),
-        {ok, OpenOptions}  = open_options(Options),
-        {ok, SocketOptions}  = socket_options(Options),
         case start_link(StartOptions, []) of
             {ok, Pid} ->
-                call(Pid, {open, ip_comm, OpenOptions, SocketOptions}, plain);
+                call(Pid, {open, ip_comm, Options}, plain);
             Error1 ->
                 Error1
         end
@@ -153,11 +151,9 @@ start_standalone(Options) ->
 start_service(Options) ->
     try
         {ok, StartOptions} = start_options(Options),
-        {ok, OpenOptions}  = open_options(Options),
-        {ok, SocketOptions}  = socket_options(Options),
         case ftp_sup:start_child([[[{client, self()} | StartOptions], []]]) of
             {ok, Pid} ->
-                call(Pid, {open, ip_comm, OpenOptions, SocketOptions}, plain);
+                call(Pid, {open, ip_comm, Options}, plain);
             Error1 ->
                 Error1
         end
@@ -202,20 +198,7 @@ service_info(Pid) ->
 
 %% <BACKWARD-COMPATIBILLITY>
 open({option_list, Options}) when is_list(Options) ->
-    try
-        {ok, StartOptions} = start_options(Options),
-        {ok, OpenOptions}  = open_options(Options),
-        {ok, SockOpts}  = socket_options(Options),
-        case ftp_sup:start_child([[[{client, self()} | StartOptions], []]]) of
-            {ok, Pid} ->
-                call(Pid, {open, ip_comm, OpenOptions, SockOpts}, plain);
-            Error1 ->
-                Error1
-        end
-    catch
-        throw:Error2 ->
-            Error2
-    end;
+    start_service(Options);
 %% </BACKWARD-COMPATIBILLITY>
 
 open(Host) ->
@@ -229,29 +212,9 @@ open(Host, Port) when is_integer(Port) ->
     open(Host, [{port, Port}]);
 %% </BACKWARD-COMPATIBILLITY>
 
-open(Host, Opts) when is_list(Opts) ->
-    try
-        {ok, StartOptions} = start_options(Opts),
-        {ok, OpenOptions}  = open_options([{host, Host}|Opts]),
-        {ok, SocketOptions}  = socket_options(Opts),
-        case start_link(StartOptions, []) of
-            {ok, Pid} ->
-                do_open(Pid, OpenOptions, SocketOptions, tls_options(Opts));
-            Error1 ->
-                Error1
-        end
-    catch
-        throw:Error2 ->
-            Error2
-    end.
+open(Host, Options) when is_list(Options) ->
+    start_standalone([{host,Host}|Options]).
 
-do_open(Pid, OpenOptions, SocketOptions, TLSOpts) ->
-    case call(Pid, {open, ip_comm, OpenOptions, SocketOptions}, plain) of
-        {ok, Pid} ->
-            maybe_tls_upgrade(Pid, TLSOpts);
-        Error ->
-            Error
-    end.
 %%--------------------------------------------------------------------------
 %% user(Pid, User, Pass, <Acc>) -> ok | {error, euser} | {error, econn}
 %%                                    | {error, eacct}
@@ -1033,7 +996,11 @@ handle_call({_,latest_ctrl_response}, _, #state{latest_ctrl_response=Resp} = Sta
 handle_call({Pid, _}, _, #state{owner = Owner} = State) when Owner =/= Pid ->
     {reply, {error, not_connection_owner}, State};
 
-handle_call({_, {open, ip_comm, Opts, {CtrlOpts, DataPassOpts, DataActOpts}}}, From, State) ->
+handle_call({_, {open, ip_comm, Options}}, From, State) ->
+    {ok, Opts} = open_options(Options),
+    {ok, {CtrlOpts, DataPassOpts, DataActOpts}} = socket_options(Options),
+    {ok, TLSOpts} = tls_options(Options),
+
     case key_search(host, Opts, undefined) of
         undefined ->
             {stop, normal, {error, ehost}, State};
@@ -1058,6 +1025,8 @@ handle_call({_, {open, ip_comm, Opts, {CtrlOpts, DataPassOpts, DataActOpts}}}, F
                                  ftp_extension = FtpExt},
 
             case setup_ctrl_connection(Host, Port, Timeout, State2) of
+                {ok, State3, WaitTimeout} when is_list(TLSOpts) ->
+                    {noreply, State3#state{tls_options = TLSOpts}, WaitTimeout};
                 {ok, State3, WaitTimeout} ->
                     {noreply, State3, WaitTimeout};
                 {error, _Reason} ->
@@ -1066,11 +1035,6 @@ handle_call({_, {open, ip_comm, Opts, {CtrlOpts, DataPassOpts, DataActOpts}}}, F
             end
     end;
 
-handle_call({_, {open, tls_upgrade, TLSOptions}}, From, State0) ->
-    _ = send_ctrl_message(State0, mk_cmd("AUTH TLS", [])),
-    State = activate_ctrl_connection(State0),
-    {noreply, State#state{client = From, caller = open, tls_options = TLSOptions}};
-
 handle_call({_, {user, User, Password}}, From,
             #state{csock = CSock} = State) when (CSock =/= undefined) ->
     handle_user(User, Password, "", State#state{client = From});
@@ -1591,12 +1555,22 @@ handle_user_account(Acc, State0) ->
 %%--------------------------------------------------------------------------
 %% handle_ctrl_result
 %%--------------------------------------------------------------------------
+handle_ctrl_result({pos_compl, _}, #state{csock = {tcp, _Socket},
+                                          tls_options = TLSOptions,
+                                          timeout = Timeout,
+                                          caller = open}
+                   = State0) when is_list(TLSOptions) ->
+    _ = send_ctrl_message(State0, mk_cmd("AUTH TLS", [])),
+    State = activate_ctrl_connection(State0),
+    {noreply, State, Timeout};
+
 handle_ctrl_result({tls_upgrade, _}, #state{csock = {tcp, Socket},
                                             tls_options = TLSOptions,
                                             timeout = Timeout,
                                             caller = open, client = From}
-                   = State0) ->
+                   = State0) when is_list(TLSOptions) ->
     ?DBG('<--ctrl ssl:connect(~p, ~p)~n~p~n',[Socket,TLSOptions,State0]),
+    catch ssl:start(),
     case ssl:connect(Socket, TLSOptions, Timeout) of
         {ok, TLSSocket} ->
             State1 = State0#state{csock = {ssl,TLSSocket}},
@@ -2429,12 +2403,6 @@ peername({ssl, Socket}) -> ssl:peername(Socket).
 sockname({tcp, Socket}) -> inet:sockname(Socket);
 sockname({ssl, Socket}) -> ssl:sockname(Socket).
 
-maybe_tls_upgrade(Pid, undefined) ->
-    {ok, Pid};
-maybe_tls_upgrade(Pid, TLSOptions) ->
-    catch ssl:start(),
-    call(Pid, {open, tls_upgrade, TLSOptions}, plain).
-
 start_chunk(#state{tls_upgrading_data_connection = {true, CTRL, _}} = State) ->
     State#state{tls_upgrading_data_connection = {true, CTRL, ?MODULE, start_chunk, undefined}};
 start_chunk(#state{client = From} = State) ->
@@ -2592,7 +2560,7 @@ valid_socket_option(_) -> true.
 
 tls_options(Options) ->
     %% Options will be validated by ssl application
-    proplists:get_value(tls, Options, undefined).
+    {ok, proplists:get_value(tls, Options, undefined)}.
 
 validate_options([], [], Acc) ->
     {ok, lists:reverse(Acc)};
-- 
2.26.2

openSUSE Build Service is sponsored by