Fix svace defects
[platform/core/security/pubkey-pinning.git] / test / gnutls_test.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file        gnutls_sample.cpp
18  * @author      Kyungwook Tak (k.tak@samsung.com)
19  * @version     1.0
20  * @brief       tpkp_gnutls unit test.
21  */
22 #include <iostream>
23 #include <vector>
24 #include <string>
25 #include <thread>
26
27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netdb.h>
31
32 #include <gnutls/gnutls.h>
33 #include <tpkp_gnutls.h>
34 #include <boost/test/unit_test.hpp>
35
36 namespace {
37
38 struct DataSet {
39         gnutls_session_t session;
40         gnutls_certificate_credentials_t cred;
41         int sockfd;
42 };
43
44 static std::vector<std::string> s_urlList = {
45         "www.google.com",
46         "www.youtube.com",
47         "www.spideroak.com",
48         "www.facebook.com",
49         "www.dropbox.com",
50         "www.twitter.com",
51         "www.hackerrank.com", /* no pinned data exist */
52         "www.algospot.com"    /* no pinned data exist */
53 };
54
55 void connectWithUrl(const std::string &url, int &sockfd)
56 {
57         struct addrinfo *result;
58         struct addrinfo hints;
59         memset(&hints, 0x00, sizeof(struct addrinfo));
60         hints.ai_family = AF_UNSPEC;
61         hints.ai_socktype = SOCK_STREAM;
62         hints.ai_flags = AI_CANONNAME;
63
64         int s = getaddrinfo(url.c_str(), "https", &hints, &result);
65         BOOST_REQUIRE_MESSAGE(s == 0, "getaddrinfo err code: " << s << " desc: " << gai_strerror(s));
66
67         struct addrinfo *rp;
68         for (rp = result; rp != nullptr; rp = rp->ai_next) {
69                 sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
70                 if (sockfd == -1)
71                         continue;
72
73                 if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) != -1)
74                         break;
75
76                 close(sockfd);
77         }
78
79         BOOST_REQUIRE_MESSAGE(rp != nullptr, "Could not connect on url: " << url);
80
81         std::cout << "url[" << url << "] canonname[" << result->ai_canonname << "] connected!" << std::endl;
82
83         freeaddrinfo(result);
84 }
85
86 inline gnutls_certificate_credentials_t makeDefaultCred(gnutls_certificate_verify_function *verify_callback)
87 {
88         gnutls_certificate_credentials_t cred;
89
90         int ret = gnutls_certificate_allocate_credentials(&cred);
91         BOOST_REQUIRE_MESSAGE(
92                 ret == GNUTLS_E_SUCCESS,
93                 "Failed to gnutls_certificate_allocate_credentials: " << gnutls_strerror(ret));
94
95         ret = gnutls_certificate_set_x509_trust_file(cred, "/etc/ssl/ca-bundle.pem", GNUTLS_X509_FMT_PEM);
96         BOOST_REQUIRE_MESSAGE(
97                 ret > 0,
98                 "Failed to gnutls_certificate_set_x509_trust_file ret: " << ret);
99
100         gnutls_certificate_set_verify_function(cred, verify_callback);
101
102         return cred;
103 }
104
105 DataSet makeDefaultSession(const std::string &url)
106 {
107         DataSet data;
108
109         data.cred = makeDefaultCred(&tpkp_gnutls_verify_callback);
110
111         int ret = gnutls_init(&data.session, GNUTLS_CLIENT);
112         BOOST_REQUIRE_MESSAGE(
113                 ret == GNUTLS_E_SUCCESS,
114                 "Failed to gnutls init session: " << gnutls_strerror(ret));
115
116         ret = gnutls_set_default_priority(data.session);
117         BOOST_REQUIRE_MESSAGE(
118                 ret == GNUTLS_E_SUCCESS,
119                 "Failed to set default priority on session: " << gnutls_strerror(ret));
120
121         ret = gnutls_credentials_set(data.session, GNUTLS_CRD_CERTIFICATE, data.cred);
122         BOOST_REQUIRE_MESSAGE(
123                 ret == GNUTLS_E_SUCCESS,
124                 "Failed to gnutls_credentials_set: " << gnutls_strerror(ret));
125
126         connectWithUrl(url, data.sockfd);
127
128         BOOST_REQUIRE_MESSAGE(
129                 tpkp_gnutls_set_url_data(url.c_str()) == TPKP_E_NONE,
130                 "Failed to tpkp_gnutls_set_url_data.");
131
132         gnutls_transport_set_int(data.session, data.sockfd);
133         gnutls_handshake_set_timeout(data.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
134
135         return data;
136 }
137
138 DataSet makeSessionWithoutPinning(const std::string &url)
139 {
140         DataSet data;
141
142         int ret = gnutls_certificate_allocate_credentials(&data.cred);
143         BOOST_REQUIRE_MESSAGE(
144                 ret == GNUTLS_E_SUCCESS,
145                 "Failed to gnutls_certificate_allocate_credentials: " << gnutls_strerror(ret));
146
147         ret = gnutls_init(&data.session, GNUTLS_CLIENT);
148         BOOST_REQUIRE_MESSAGE(
149                 ret == GNUTLS_E_SUCCESS,
150                 "Failed to gnutls init session: " << gnutls_strerror(ret));
151
152         ret = gnutls_set_default_priority(data.session);
153         BOOST_REQUIRE_MESSAGE(
154                 ret == GNUTLS_E_SUCCESS,
155                 "Failed to set default priority on session: " << gnutls_strerror(ret));
156
157         ret = gnutls_credentials_set(data.session, GNUTLS_CRD_CERTIFICATE, data.cred);
158         BOOST_REQUIRE_MESSAGE(
159                 ret == GNUTLS_E_SUCCESS,
160                 "Failed to gnutls_credentials_set: " << gnutls_strerror(ret));
161
162         connectWithUrl(url, data.sockfd);
163
164         gnutls_transport_set_int(data.session, data.sockfd);
165         gnutls_handshake_set_timeout(data.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
166
167         return data;
168 }
169
170 DataSet makeDefaultSessionGlobal(const std::string &url)
171 {
172         int ret = gnutls_global_init();
173         BOOST_REQUIRE_MESSAGE(
174                 ret == GNUTLS_E_SUCCESS,
175                 "Failed to gnutls global init: " << gnutls_strerror(ret));
176
177         return makeDefaultSession(url);
178 }
179
180 void performHandshake(DataSet &data)
181 {
182         int ret;
183         do {
184                 ret = gnutls_handshake(data.session);
185         } while (ret != GNUTLS_E_SUCCESS && gnutls_error_is_fatal(ret) == 0);
186
187         BOOST_REQUIRE_MESSAGE(
188                 ret == GNUTLS_E_SUCCESS,
189                 "Handshake failed! err code: " << ret << " desc: " << gnutls_strerror(ret));
190 }
191
192 void cleanup(DataSet &data)
193 {
194         gnutls_bye(data.session, GNUTLS_SHUT_RDWR);
195         if (data.sockfd > 0)
196                 close(data.sockfd);
197         gnutls_certificate_free_credentials(data.cred);
198         gnutls_deinit(data.session);
199
200         tpkp_gnutls_cleanup();
201 }
202
203 void cleanupGlobal(DataSet &data)
204 {
205         cleanup(data);
206         gnutls_global_deinit();
207 }
208
209 void perform(const std::string &url)
210 {
211         DataSet data = makeDefaultSession(url);
212         performHandshake(data);
213         cleanup(data);
214 }
215
216 void performWithoutPinning(const std::string &url)
217 {
218         DataSet data = makeSessionWithoutPinning(url);
219         performHandshake(data);
220         cleanup(data);
221 }
222
223 }
224
225 BOOST_AUTO_TEST_SUITE(TPKP_GNUTLS_TEST)
226
227 BOOST_AUTO_TEST_CASE(T00101_positive_1)
228 {
229         gnutls_global_init();
230
231         perform(s_urlList[0]);
232
233         gnutls_global_deinit();
234 }
235
236 BOOST_AUTO_TEST_CASE(T00102_positive_2)
237 {
238         gnutls_global_init();
239
240         perform(s_urlList[1]);
241
242         gnutls_global_deinit();
243 }
244
245 BOOST_AUTO_TEST_CASE(T00103_positive_3)
246 {
247         gnutls_global_init();
248
249         perform(s_urlList[2]);
250
251         gnutls_global_deinit();
252 }
253
254 BOOST_AUTO_TEST_CASE(T00104_positive_4)
255 {
256         gnutls_global_init();
257
258         perform(s_urlList[3]);
259
260         gnutls_global_deinit();
261 }
262
263 BOOST_AUTO_TEST_CASE(T00105_positive_5)
264 {
265         gnutls_global_init();
266
267         perform(s_urlList[4]);
268
269         gnutls_global_deinit();
270 }
271
272 BOOST_AUTO_TEST_CASE(T00106_positive_6)
273 {
274         gnutls_global_init();
275
276         perform(s_urlList[5]);
277
278         gnutls_global_deinit();
279 }
280
281 BOOST_AUTO_TEST_CASE(T00107_positive_7)
282 {
283         gnutls_global_init();
284
285         perform(s_urlList[6]);
286
287         gnutls_global_deinit();
288 }
289
290 BOOST_AUTO_TEST_CASE(T00108_positive_8)
291 {
292         gnutls_global_init();
293
294         perform(s_urlList[7]);
295
296         gnutls_global_deinit();
297 }
298
299 BOOST_AUTO_TEST_CASE(T00109_positive_all_single_thread)
300 {
301         gnutls_global_init();
302
303         for (const auto &url : s_urlList)
304                 perform(url);
305
306         gnutls_global_deinit();
307 }
308
309 BOOST_AUTO_TEST_CASE(T00110_positive_all_single_thread_without_pinning)
310 {
311         gnutls_global_init();
312
313         for (const auto &url : s_urlList)
314                 performWithoutPinning(url);
315
316         gnutls_global_deinit();
317 }
318
319 BOOST_AUTO_TEST_SUITE_END()