1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "tlssocket_module.h"
17 
18 #include <initializer_list>
19 #include <napi/native_common.h>
20 
21 #include "common_context.h"
22 #include "event_manager.h"
23 #include "module_template.h"
24 #include "monitor.h"
25 #include "napi_utils.h"
26 #include "netstack_log.h"
27 #include "tls.h"
28 #include "tls_bind_context.h"
29 #include "tls_connect_context.h"
30 #include "tls_extra_context.h"
31 #include "tls_napi_context.h"
32 #include "tls_send_context.h"
33 #include "tls_init_context.h"
34 #include "tlssocket_async_work.h"
35 
36 namespace OHOS {
37 namespace NetStack {
38 namespace TlsSocket {
39 namespace {
40 static constexpr const char *PROTOCOL_TLSV13 = "TLSv13";
41 static constexpr const char *PROTOCOL_TLSV12 = "TLSv12";
42 
Finalize(napi_env,void * data,void *)43 void Finalize(napi_env, void *data, void *)
44 {
45     NETSTACK_LOGI("tls socket is finalized");
46     auto manager = reinterpret_cast<EventManager *>(data);
47     if (manager != nullptr) {
48         EventManager::SetInvalid(manager);
49     }
50 }
51 } // namespace
52 
GetCertificate(napi_env env,napi_callback_info info)53 napi_value TLSSocketModuleExports::TLSSocket::GetCertificate(napi_env env, napi_callback_info info)
54 {
55     return ModuleTemplate::Interface<GetCertificateContext>(env, info, FUNCTION_GET_CERTIFICATE, nullptr,
56                                                             TLSSocketAsyncWork::ExecGetCertificate,
57                                                             TLSSocketAsyncWork::GetCertificateCallback);
58 }
59 
GetProtocol(napi_env env,napi_callback_info info)60 napi_value TLSSocketModuleExports::TLSSocket::GetProtocol(napi_env env, napi_callback_info info)
61 {
62     return ModuleTemplate::Interface<GetCipherSuitesContext>(env, info, FUNCTION_GET_PROTOCOL, nullptr,
63                                                              TLSSocketAsyncWork::ExecGetProtocol,
64                                                              TLSSocketAsyncWork::GetProtocolCallback);
65 }
66 
Connect(napi_env env,napi_callback_info info)67 napi_value TLSSocketModuleExports::TLSSocket::Connect(napi_env env, napi_callback_info info)
68 {
69     return ModuleTemplate::Interface<TLSConnectContext>(
70         env, info, FUNCTION_CONNECT, nullptr, TLSSocketAsyncWork::ExecConnect, TLSSocketAsyncWork::ConnectCallback);
71 }
72 
GetCipherSuites(napi_env env,napi_callback_info info)73 napi_value TLSSocketModuleExports::TLSSocket::GetCipherSuites(napi_env env, napi_callback_info info)
74 {
75     return ModuleTemplate::Interface<GetCipherSuitesContext>(env, info, FUNCTION_GET_CIPHER_SUITE, nullptr,
76                                                              TLSSocketAsyncWork::ExecGetCipherSuites,
77                                                              TLSSocketAsyncWork::GetCipherSuitesCallback);
78 }
79 
GetRemoteCertificate(napi_env env,napi_callback_info info)80 napi_value TLSSocketModuleExports::TLSSocket::GetRemoteCertificate(napi_env env, napi_callback_info info)
81 {
82     return ModuleTemplate::Interface<GetRemoteCertificateContext>(env, info, FUNCTION_GET_REMOTE_CERTIFICATE, nullptr,
83                                                                   TLSSocketAsyncWork::ExecGetRemoteCertificate,
84                                                                   TLSSocketAsyncWork::GetRemoteCertificateCallback);
85 }
86 
GetSignatureAlgorithms(napi_env env,napi_callback_info info)87 napi_value TLSSocketModuleExports::TLSSocket::GetSignatureAlgorithms(napi_env env, napi_callback_info info)
88 {
89     return ModuleTemplate::Interface<GetSignatureAlgorithmsContext>(
90         env, info, FUNCTION_GET_SIGNATURE_ALGORITHMS, nullptr, TLSSocketAsyncWork::ExecGetSignatureAlgorithms,
91         TLSSocketAsyncWork::GetSignatureAlgorithmsCallback);
92 }
93 
Send(napi_env env,napi_callback_info info)94 napi_value TLSSocketModuleExports::TLSSocket::Send(napi_env env, napi_callback_info info)
95 {
96     return ModuleTemplate::Interface<TLSSendContext>(env, info, FUNCTION_SEND, nullptr, TLSSocketAsyncWork::ExecSend,
97                                                      TLSSocketAsyncWork::SendCallback);
98 }
99 
Close(napi_env env,napi_callback_info info)100 napi_value TLSSocketModuleExports::TLSSocket::Close(napi_env env, napi_callback_info info)
101 {
102     return ModuleTemplate::Interface<TLSNapiContext>(env, info, FUNCTION_CLOSE, nullptr, TLSSocketAsyncWork::ExecClose,
103                                                      TLSSocketAsyncWork::CloseCallback);
104 }
105 
Bind(napi_env env,napi_callback_info info)106 napi_value TLSSocketModuleExports::TLSSocket::Bind(napi_env env, napi_callback_info info)
107 {
108     return ModuleTemplate::Interface<TLSBindContext>(env, info, FUNCTION_BIND, nullptr, TLSSocketAsyncWork::ExecBind,
109                                                      TLSSocketAsyncWork::BindCallback);
110 }
111 
GetState(napi_env env,napi_callback_info info)112 napi_value TLSSocketModuleExports::TLSSocket::GetState(napi_env env, napi_callback_info info)
113 {
114     return ModuleTemplate::Interface<TLSGetStateContext>(
115         env, info, FUNCTION_GET_STATE, nullptr, TLSSocketAsyncWork::ExecGetState, TLSSocketAsyncWork::GetStateCallback);
116 }
117 
GetRemoteAddress(napi_env env,napi_callback_info info)118 napi_value TLSSocketModuleExports::TLSSocket::GetRemoteAddress(napi_env env, napi_callback_info info)
119 {
120     return ModuleTemplate::Interface<TLSGetRemoteAddressContext>(env, info, FUNCTION_GET_REMOTE_ADDRESS, nullptr,
121                                                                  TLSSocketAsyncWork::ExecGetRemoteAddress,
122                                                                  TLSSocketAsyncWork::GetRemoteAddressCallback);
123 }
124 
GetLocalAddress(napi_env env,napi_callback_info info)125 napi_value TLSSocketModuleExports::TLSSocket::GetLocalAddress(napi_env env, napi_callback_info info)
126 {
127     return ModuleTemplate::Interface<TLSGetLocalAddressContext>(env, info, FUNCTION_GET_LOCAL_ADDRESS, nullptr,
128                                                                  TLSSocketAsyncWork::ExecGetLocalAddress,
129                                                                  TLSSocketAsyncWork::GetLocalAddressCallback);
130 }
131 
SetExtraOptions(napi_env env,napi_callback_info info)132 napi_value TLSSocketModuleExports::TLSSocket::SetExtraOptions(napi_env env, napi_callback_info info)
133 {
134     return ModuleTemplate::Interface<TLSSetExtraOptionsContext>(env, info, FUNCTION_BIND, nullptr,
135                                                                 TLSSocketAsyncWork::ExecSetExtraOptions,
136                                                                 TLSSocketAsyncWork::SetExtraOptionsCallback);
137 }
138 
On(napi_env env,napi_callback_info info)139 napi_value TLSSocketModuleExports::TLSSocket::On(napi_env env, napi_callback_info info)
140 {
141     return DelayedSingleton<Monitor>::GetInstance()->On(env, info);
142 }
143 
Off(napi_env env,napi_callback_info info)144 napi_value TLSSocketModuleExports::TLSSocket::Off(napi_env env, napi_callback_info info)
145 {
146     return DelayedSingleton<Monitor>::GetInstance()->Off(env, info);
147 }
148 
DefineTLSSocketClass(napi_env env,napi_value exports)149 void TLSSocketModuleExports::DefineTLSSocketClass(napi_env env, napi_value exports)
150 {
151     std::initializer_list<napi_property_descriptor> functions = {
152         DECLARE_NAPI_FUNCTION(TLSSocket::FUNCTION_GET_CERTIFICATE, TLSSocket::GetCertificate),
153         DECLARE_NAPI_FUNCTION(TLSSocket::FUNCTION_GET_REMOTE_CERTIFICATE, TLSSocket::GetRemoteCertificate),
154         DECLARE_NAPI_FUNCTION(TLSSocket::FUNCTION_GET_SIGNATURE_ALGORITHMS, TLSSocket::GetSignatureAlgorithms),
155         DECLARE_NAPI_FUNCTION(TLSSocket::FUNCTION_GET_PROTOCOL, TLSSocket::GetProtocol),
156         DECLARE_NAPI_FUNCTION(TLSSocket::FUNCTION_CONNECT, TLSSocket::Connect),
157         DECLARE_NAPI_FUNCTION(TLSSocket::FUNCTION_GET_CIPHER_SUITE, TLSSocket::GetCipherSuites),
158         DECLARE_NAPI_FUNCTION(TLSSocket::FUNCTION_SEND, TLSSocket::Send),
159         DECLARE_NAPI_FUNCTION(TLSSocket::FUNCTION_CLOSE, TLSSocket::Close),
160         DECLARE_NAPI_FUNCTION(TLSSocket::FUNCTION_BIND, TLSSocket::Bind),
161         DECLARE_NAPI_FUNCTION(TLSSocket::FUNCTION_GET_STATE, TLSSocket::GetState),
162         DECLARE_NAPI_FUNCTION(TLSSocket::FUNCTION_GET_REMOTE_ADDRESS, TLSSocket::GetRemoteAddress),
163         DECLARE_NAPI_FUNCTION(TLSSocket::FUNCTION_GET_LOCAL_ADDRESS, TLSSocket::GetLocalAddress),
164         DECLARE_NAPI_FUNCTION(TLSSocket::FUNCTION_SET_EXTRA_OPTIONS, TLSSocket::SetExtraOptions),
165         DECLARE_NAPI_FUNCTION(TLSSocket::FUNCTION_ON, TLSSocket::On),
166         DECLARE_NAPI_FUNCTION(TLSSocket::FUNCTION_OFF, TLSSocket::Off),
167     };
168     ModuleTemplate::DefineClass(env, exports, functions, INTERFACE_TLS_SOCKET);
169 }
170 
InitProtocol(napi_env env,napi_value exports)171 void TLSSocketModuleExports::InitProtocol(napi_env env, napi_value exports)
172 {
173     std::initializer_list<napi_property_descriptor> properties = {
174         DECLARE_NAPI_STATIC_PROPERTY(PROTOCOL_TLSV12, NapiUtils::CreateStringUtf8(env, PROTOCOL_TLS_V12)),
175         DECLARE_NAPI_STATIC_PROPERTY(PROTOCOL_TLSV13, NapiUtils::CreateStringUtf8(env, PROTOCOL_TLS_V13)),
176     };
177 
178     napi_value protocol = NapiUtils::CreateObject(env);
179     NapiUtils::DefineProperties(env, protocol, properties);
180     NapiUtils::SetNamedProperty(env, exports, INTERFACE_PROTOCOL, protocol);
181 }
182 
ConstructTLSSocketInstance(napi_env env,napi_callback_info info)183 napi_value TLSSocketModuleExports::ConstructTLSSocketInstance(napi_env env, napi_callback_info info)
184 {
185     napi_value result = ModuleTemplate::NewInstance(env, info, INTERFACE_TLS_SOCKET, Finalize);
186     if (result == nullptr) {
187         return nullptr;
188     }
189 
190     size_t paramsCount = MAX_PARAM_NUM;
191     napi_value params[MAX_PARAM_NUM] = {nullptr};
192     NAPI_CALL(env, napi_get_cb_info(env, info, &paramsCount, params, nullptr, nullptr));
193     if (paramsCount == 0) {
194         return result;
195     }
196 
197     EventManager *manager = nullptr;
198     auto napiRet = napi_unwrap(env, result, reinterpret_cast<void **>(&manager));
199     if (napiRet != napi_ok) {
200         NETSTACK_LOGE("get event manager in napi_unwrap failed, napiRet is %{public}d", napiRet);
201         return nullptr;
202     }
203 
204     auto context = new TLSInitContext(env, manager);
205     if (context == nullptr) {
206         NETSTACK_LOGE("new TLSInitContext failed, no enough memory");
207         return nullptr;
208     }
209 
210     context->ParseParams(params, paramsCount);
211     if (context->IsParseOK()) {
212         TLSSocketAsyncWork::ExecInit(env, (void *)context);
213     }
214 
215     if (context->IsNeedThrowException()) { // only api9 or later need throw exception.
216         napi_throw_error(env, std::to_string(context->GetErrorCode()).c_str(), context->GetErrorMessage().c_str());
217         delete context;
218         return nullptr;
219     }
220 
221     delete context;
222     return result;
223 }
224 
InitTLSSocketProperties(napi_env env,napi_value exports)225 void TLSSocketModuleExports::InitTLSSocketProperties(napi_env env, napi_value exports)
226 {
227     std::initializer_list<napi_property_descriptor> properties = {
228         DECLARE_NAPI_FUNCTION(FUNCTION_CONSTRUCTOR_TLS_SOCKET_INSTANCE, ConstructTLSSocketInstance),
229     };
230     NapiUtils::DefineProperties(env, exports, properties);
231 }
232 
InitTLSSocketModule(napi_env env,napi_value exports)233 napi_value TLSSocketModuleExports::InitTLSSocketModule(napi_env env, napi_value exports)
234 {
235     DefineTLSSocketClass(env, exports);
236     InitTLSSocketProperties(env, exports);
237     InitProtocol(env, exports);
238     return exports;
239 }
240 } // namespace TlsSocket
241 } // namespace NetStack
242 } // namespace OHOS
243