2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @file gnutls_sample.cpp
18 * @author Kyungwook Tak (k.tak@samsung.com)
20 * @brief tpkp_gnutls unit test.
28 #include <sys/types.h>
29 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
34 #include <gnutls/gnutls.h>
35 #include <tpkp_gnutls.h>
36 #include <boost/test/unit_test.hpp>
41 gnutls_session_t session;
42 gnutls_certificate_credentials_t cred;
46 static std::vector<std::string> s_urlList = {
53 "www.hackerrank.com", /* no pinned data exist */
54 "www.algospot.com" /* no pinned data exist */
57 void connectWithUrl(const std::string &url, int &sockfd)
59 struct addrinfo *result;
60 struct addrinfo hints;
61 memset(&hints, 0x00, sizeof(struct addrinfo));
62 hints.ai_family = AF_UNSPEC;
63 hints.ai_socktype = SOCK_STREAM;
64 hints.ai_flags = AI_CANONNAME;
66 int s = getaddrinfo(url.c_str(), "https", &hints, &result);
67 BOOST_REQUIRE_MESSAGE(s == 0, "getaddrinfo err code: " << s << " desc: " << gai_strerror(s));
70 for (rp = result; rp != nullptr; rp = rp->ai_next) {
71 sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
75 if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) != -1) {
76 char *ipaddr = inet_ntoa(*((struct in_addr *)rp->ai_addr));
83 BOOST_REQUIRE_MESSAGE(rp != nullptr, "Could not connect on url: " << url);
85 std::cout << "url[" << url << "] canonname[" << result->ai_canonname << "] connected!" << std::endl;
90 inline gnutls_certificate_credentials_t makeDefaultCred(gnutls_certificate_verify_function *verify_callback)
92 gnutls_certificate_credentials_t cred;
94 int ret = gnutls_certificate_allocate_credentials(&cred);
95 BOOST_REQUIRE_MESSAGE(
96 ret == GNUTLS_E_SUCCESS,
97 "Failed to gnutls_certificate_allocate_credentials: " << gnutls_strerror(ret));
99 ret = gnutls_certificate_set_x509_trust_file(cred, "/etc/ssl/ca-bundle.pem", GNUTLS_X509_FMT_PEM);
100 BOOST_REQUIRE_MESSAGE(
102 "Failed to gnutls_certificate_set_x509_trust_file ret: " << ret);
104 gnutls_certificate_set_verify_function(cred, verify_callback);
109 DataSet makeDefaultSession(const std::string &url)
113 data.cred = makeDefaultCred(&tpkp_gnutls_verify_callback);
115 int ret = gnutls_init(&data.session, GNUTLS_CLIENT);
116 BOOST_REQUIRE_MESSAGE(
117 ret == GNUTLS_E_SUCCESS,
118 "Failed to gnutls init session: " << gnutls_strerror(ret));
120 ret = gnutls_set_default_priority(data.session);
121 BOOST_REQUIRE_MESSAGE(
122 ret == GNUTLS_E_SUCCESS,
123 "Failed to set default priority on session: " << gnutls_strerror(ret));
125 ret = gnutls_credentials_set(data.session, GNUTLS_CRD_CERTIFICATE, data.cred);
126 BOOST_REQUIRE_MESSAGE(
127 ret == GNUTLS_E_SUCCESS,
128 "Failed to gnutls_credentials_set: " << gnutls_strerror(ret));
130 connectWithUrl(url, data.sockfd);
132 BOOST_REQUIRE_MESSAGE(
133 tpkp_gnutls_set_url_data(url.c_str()) == TPKP_E_NONE,
134 "Failed to tpkp_gnutls_set_url_data.");
136 gnutls_transport_set_int(data.session, data.sockfd);
137 gnutls_handshake_set_timeout(data.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
142 DataSet makeSessionWithoutPinning(const std::string &url)
146 int ret = gnutls_certificate_allocate_credentials(&data.cred);
147 BOOST_REQUIRE_MESSAGE(
148 ret == GNUTLS_E_SUCCESS,
149 "Failed to gnutls_certificate_allocate_credentials: " << gnutls_strerror(ret));
151 ret = gnutls_init(&data.session, GNUTLS_CLIENT);
152 BOOST_REQUIRE_MESSAGE(
153 ret == GNUTLS_E_SUCCESS,
154 "Failed to gnutls init session: " << gnutls_strerror(ret));
156 ret = gnutls_set_default_priority(data.session);
157 BOOST_REQUIRE_MESSAGE(
158 ret == GNUTLS_E_SUCCESS,
159 "Failed to set default priority on session: " << gnutls_strerror(ret));
161 ret = gnutls_credentials_set(data.session, GNUTLS_CRD_CERTIFICATE, data.cred);
162 BOOST_REQUIRE_MESSAGE(
163 ret == GNUTLS_E_SUCCESS,
164 "Failed to gnutls_credentials_set: " << gnutls_strerror(ret));
166 connectWithUrl(url, data.sockfd);
168 gnutls_transport_set_int(data.session, data.sockfd);
169 gnutls_handshake_set_timeout(data.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
174 DataSet makeDefaultSessionGlobal(const std::string &url)
176 int ret = gnutls_global_init();
177 BOOST_REQUIRE_MESSAGE(
178 ret == GNUTLS_E_SUCCESS,
179 "Failed to gnutls global init: " << gnutls_strerror(ret));
181 return makeDefaultSession(url);
184 void performHandshake(DataSet &data)
188 ret = gnutls_handshake(data.session);
189 } while (ret != GNUTLS_E_SUCCESS && gnutls_error_is_fatal(ret) == 0);
191 BOOST_REQUIRE_MESSAGE(
192 ret == GNUTLS_E_SUCCESS,
193 "Handshake failed! err code: " << ret << " desc: " << gnutls_strerror(ret));
196 void cleanup(DataSet &data)
198 gnutls_bye(data.session, GNUTLS_SHUT_RDWR);
200 gnutls_certificate_free_credentials(data.cred);
201 gnutls_deinit(data.session);
203 tpkp_gnutls_cleanup();
206 void cleanupGlobal(DataSet &data)
209 gnutls_global_deinit();
212 void perform(const std::string &url)
214 DataSet data = makeDefaultSession(url);
215 performHandshake(data);
219 void performWithoutPinning(const std::string &url)
221 DataSet data = makeSessionWithoutPinning(url);
222 performHandshake(data);
228 BOOST_AUTO_TEST_SUITE(TPKP_GNUTLS_TEST)
230 BOOST_AUTO_TEST_CASE(T00101_positive_1)
232 gnutls_global_init();
234 perform(s_urlList[0]);
236 gnutls_global_deinit();
239 BOOST_AUTO_TEST_CASE(T00102_positive_2)
241 gnutls_global_init();
243 perform(s_urlList[1]);
245 gnutls_global_deinit();
248 BOOST_AUTO_TEST_CASE(T00103_positive_3)
250 gnutls_global_init();
252 perform(s_urlList[2]);
254 gnutls_global_deinit();
257 BOOST_AUTO_TEST_CASE(T00104_positive_4)
259 gnutls_global_init();
261 perform(s_urlList[3]);
263 gnutls_global_deinit();
266 BOOST_AUTO_TEST_CASE(T00105_positive_5)
268 gnutls_global_init();
270 perform(s_urlList[4]);
272 gnutls_global_deinit();
275 BOOST_AUTO_TEST_CASE(T00106_positive_6)
277 gnutls_global_init();
279 perform(s_urlList[5]);
281 gnutls_global_deinit();
284 BOOST_AUTO_TEST_CASE(T00107_positive_7)
286 gnutls_global_init();
288 perform(s_urlList[6]);
290 gnutls_global_deinit();
293 BOOST_AUTO_TEST_CASE(T00108_positive_8)
295 gnutls_global_init();
297 perform(s_urlList[7]);
299 gnutls_global_deinit();
302 BOOST_AUTO_TEST_CASE(T00109_positive_all_single_thread)
304 gnutls_global_init();
306 for (const auto &url : s_urlList)
309 gnutls_global_deinit();
312 BOOST_AUTO_TEST_CASE(T00110_positive_all_single_thread_without_pinning)
314 gnutls_global_init();
316 for (const auto &url : s_urlList)
317 performWithoutPinning(url);
319 gnutls_global_deinit();
322 BOOST_AUTO_TEST_SUITE_END()