• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "tls_connect_context.h"
17 
18 #include <cstdint>
19 #include <string>
20 #include <string_view>
21 #include <vector>
22 
23 #include "constant.h"
24 #include "napi_utils.h"
25 #include "netstack_log.h"
26 
27 namespace OHOS {
28 namespace NetStack {
29 namespace {
30 constexpr const char *ALPN_PROTOCOLS = "ALPNProtocols";
31 constexpr const char *SECURE_OPTIONS = "secureOptions";
32 constexpr const char *CA_NAME = "ca";
33 constexpr const char *CERT_NAME = "cert";
34 constexpr const char *KEY_NAME = "key";
35 constexpr const char *PASSWD_NAME = "passwd";
36 constexpr const char *PROTOCOLS_NAME = "protocols";
37 constexpr const char *SIGNATURE_ALGORITHMS = "signatureAlgorithms";
38 constexpr const char *USE_REMOTE_CIPHER_PREFER = "useRemoteCipherPrefer";
39 constexpr const char *CIPHER_SUITE = "cipherSuite";
40 constexpr const char *ADDRESS_NAME = "address";
41 constexpr const char *FAMILY_NAME = "family";
42 constexpr const char *PORT_NAME = "port";
43 constexpr uint32_t CA_CHAIN_LENGTH = 10;
44 constexpr uint32_t PROTOCOLS_SIZE = 10;
45 constexpr std::string_view PARSE_ERROR = "options is not type of TLSConnectOptions";
46 
ReadNecessaryOptions(napi_env env,napi_value secureOptions,TLSSecureOptions & secureOption)47 bool ReadNecessaryOptions(napi_env env, napi_value secureOptions, TLSSecureOptions &secureOption)
48 {
49     if (!NapiUtils::HasNamedProperty(env, secureOptions, CA_NAME)) {
50         return false;
51     }
52     napi_value caCert = NapiUtils::GetNamedProperty(env, secureOptions, CA_NAME);
53     std::vector<std::string> caVec;
54     if (NapiUtils::GetValueType(env, caCert) == napi_string) {
55         std::string ca = NapiUtils::GetStringPropertyUtf8(env, secureOptions, CA_NAME);
56         caVec.push_back(ca);
57     }
58     if (NapiUtils::GetValueType(env, caCert) == napi_object) {
59         uint32_t arrayLong = NapiUtils::GetArrayLength(env, caCert);
60         if (arrayLong > CA_CHAIN_LENGTH) {
61             return false;
62         }
63         napi_value element = nullptr;
64         for (uint32_t i = 0; i < arrayLong; i++) {
65             element = NapiUtils::GetArrayElement(env, caCert, i);
66             std::string ca = NapiUtils::GetStringFromValueUtf8(env, element);
67             caVec.push_back(ca);
68         }
69     }
70     secureOption.SetCaChain(caVec);
71 
72     if (NapiUtils::HasNamedProperty(env, secureOptions, KEY_NAME)) {
73         secureOption.SetKey(SecureData(NapiUtils::GetStringPropertyUtf8(env, secureOptions, KEY_NAME)));
74     }
75     if (NapiUtils::HasNamedProperty(env, secureOptions, CERT_NAME)) {
76         secureOption.SetCert(NapiUtils::GetStringPropertyUtf8(env, secureOptions, CERT_NAME));
77     }
78     return true;
79 }
80 } // namespace
81 
TLSConnectContext(napi_env env,EventManager * manager)82 TLSConnectContext::TLSConnectContext(napi_env env, EventManager *manager) : BaseContext(env, manager) {}
83 
ParseParams(napi_value * params,size_t paramsCount)84 void TLSConnectContext::ParseParams(napi_value *params, size_t paramsCount)
85 {
86     if (!CheckParamsType(params, paramsCount)) {
87         return;
88     }
89     connectOptions_ = ReadTLSConnectOptions(GetEnv(), params);
90 
91     if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) {
92         SetParseOK(SetCallback(params[ARG_INDEX_1]) == napi_ok);
93         return;
94     }
95     SetParseOK(true);
96 }
97 
CheckParamsType(napi_value * params,size_t paramsCount)98 bool TLSConnectContext::CheckParamsType(napi_value *params, size_t paramsCount)
99 {
100     if (paramsCount == PARAM_JUST_OPTIONS) {
101         if (NapiUtils::GetValueType(GetEnv(), params[ARG_INDEX_0]) != napi_object) {
102             NETSTACK_LOGE("tlsConnectContext first param is not object");
103             SetNeedThrowException(true);
104             SetError(PARSE_ERROR_CODE, PARSE_ERROR.data());
105             return false;
106         }
107         return true;
108     }
109 
110     if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) {
111         if (NapiUtils::GetValueType(GetEnv(), params[ARG_INDEX_0]) != napi_object) {
112             NETSTACK_LOGE("tls ConnectContext first param is not object");
113             SetNeedThrowException(true);
114             SetError(PARSE_ERROR_CODE, PARSE_ERROR.data());
115             return false;
116         }
117         if (NapiUtils::GetValueType(GetEnv(), params[ARG_INDEX_1]) != napi_function) {
118             NETSTACK_LOGE(" tls ConnectContext second param is not function");
119             return false;
120         }
121         return true;
122     }
123     return false;
124 }
125 
ReadTLSConnectOptions(napi_env env,napi_value * params)126 TLSConnectOptions TLSConnectContext::ReadTLSConnectOptions(napi_env env, napi_value *params)
127 {
128     TLSConnectOptions options;
129     NetAddress address = ReadNetAddress(GetEnv(), params);
130     TLSSecureOptions secureOption = ReadTLSSecureOptions(GetEnv(), params);
131     options.SetNetAddress(address);
132     options.SetTlsSecureOptions(secureOption);
133     if (NapiUtils::HasNamedProperty(GetEnv(), params[0], ALPN_PROTOCOLS)) {
134         napi_value alpnProtocols = NapiUtils::GetNamedProperty(GetEnv(), params[0], ALPN_PROTOCOLS);
135         uint32_t arrayLength = NapiUtils::GetArrayLength(GetEnv(), alpnProtocols);
136         arrayLength = arrayLength > PROTOCOLS_SIZE ? PROTOCOLS_SIZE : arrayLength;
137         napi_value elementValue = nullptr;
138         std::vector<std::string> alpnProtocolVec;
139         for (uint32_t i = 0; i < arrayLength; i++) {
140             elementValue = NapiUtils::GetArrayElement(GetEnv(), alpnProtocols, i);
141             std::string alpnProtocol = NapiUtils::GetStringFromValueUtf8(GetEnv(), elementValue);
142             alpnProtocolVec.push_back(alpnProtocol);
143         }
144         options.SetAlpnProtocols(alpnProtocolVec);
145     }
146     return options;
147 }
148 
ReadTLSSecureOptions(napi_env env,napi_value * params)149 TLSSecureOptions TLSConnectContext::ReadTLSSecureOptions(napi_env env, napi_value *params)
150 {
151     TLSSecureOptions secureOption;
152 
153     if (!NapiUtils::HasNamedProperty(GetEnv(), params[ARG_INDEX_0], SECURE_OPTIONS)) {
154         return secureOption;
155     }
156     napi_value secureOptions = NapiUtils::GetNamedProperty(GetEnv(), params[ARG_INDEX_0], SECURE_OPTIONS);
157     if (!ReadNecessaryOptions(env, secureOptions, secureOption)) {
158         return secureOption;
159     }
160 
161     if (NapiUtils::HasNamedProperty(GetEnv(), secureOptions, PASSWD_NAME)) {
162         secureOption.SetKeyPass(SecureData(NapiUtils::GetStringPropertyUtf8(env, secureOptions, PASSWD_NAME)));
163     }
164 
165     if (NapiUtils::HasNamedProperty(GetEnv(), secureOptions, PROTOCOLS_NAME)) {
166         napi_value protocolVector = NapiUtils::GetNamedProperty(env, secureOptions, PROTOCOLS_NAME);
167         uint32_t num = NapiUtils::GetArrayLength(GetEnv(), protocolVector);
168         num = num > PROTOCOLS_SIZE ? PROTOCOLS_SIZE : num;
169         napi_value element = nullptr;
170         std::vector<std::string> protocolVec;
171         for (uint32_t i = 0; i < num; i++) {
172             element = NapiUtils::GetArrayElement(GetEnv(), protocolVector, i);
173             std::string protocol = NapiUtils::GetStringFromValueUtf8(GetEnv(), element);
174             protocolVec.push_back(protocol);
175         }
176         secureOption.SetProtocolChain(protocolVec);
177     }
178 
179     if (NapiUtils::HasNamedProperty(GetEnv(), secureOptions, SIGNATURE_ALGORITHMS)) {
180         std::string signatureAlgorithms = NapiUtils::GetStringPropertyUtf8(env, secureOptions, SIGNATURE_ALGORITHMS);
181         secureOption.SetSignatureAlgorithms(signatureAlgorithms);
182     }
183 
184     if (NapiUtils::HasNamedProperty(GetEnv(), secureOptions, USE_REMOTE_CIPHER_PREFER)) {
185         bool useRemoteCipherPrefer = NapiUtils::GetBooleanProperty(env, secureOptions, USE_REMOTE_CIPHER_PREFER);
186         secureOption.SetUseRemoteCipherPrefer(useRemoteCipherPrefer);
187     }
188 
189     if (NapiUtils::HasNamedProperty(GetEnv(), secureOptions, CIPHER_SUITE)) {
190         std::string cipherSuite = NapiUtils::GetStringPropertyUtf8(env, secureOptions, CIPHER_SUITE);
191         secureOption.SetCipherSuite(cipherSuite);
192     }
193 
194     return secureOption;
195 }
196 
ReadNetAddress(napi_env env,napi_value * params)197 NetAddress TLSConnectContext::ReadNetAddress(napi_env env, napi_value *params)
198 {
199     NetAddress address;
200     napi_value netAddress = NapiUtils::GetNamedProperty(GetEnv(), params[0], ADDRESS_NAME);
201 
202     std::string addr = NapiUtils::GetStringPropertyUtf8(GetEnv(), netAddress, ADDRESS_NAME);
203     address.SetAddress(addr);
204     uint32_t family = NapiUtils::GetUint32Property(GetEnv(), netAddress, FAMILY_NAME);
205     if (family == 1) {
206         address.SetFamilyBySaFamily(AF_INET);
207     } else {
208         address.SetFamilyBySaFamily(AF_INET6);
209     }
210     if (NapiUtils::HasNamedProperty(GetEnv(), netAddress, PORT_NAME)) {
211         uint16_t port = static_cast<uint16_t>(NapiUtils::GetUint32Property(GetEnv(), netAddress, PORT_NAME));
212         address.SetPort(port);
213     }
214     return address;
215 }
216 } // namespace NetStack
217 } // namespace OHOS
218