-
Notifications
You must be signed in to change notification settings - Fork 0
/
tls_client.cpp
125 lines (109 loc) · 4.14 KB
/
tls_client.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*
样例代码取自Botan官方手册:
https://botan.randombit.net/manual/tls.html#code-example
Ubuntu下安装开发包的命令为:
sudo apt install libbotan-2-dev
安装Botan 2.9开发包以及g++编译器后, 可使用g++命令手动编译tls_client.cpp:
g++ -I/usr/include/botan-2 tls_client.cpp -lbotan-2
*/
#include <botan/tls_client.h>
#include <botan/tls_callbacks.h>
#include <botan/tls_session_manager.h>
#include <botan/tls_policy.h>
#include <botan/auto_rng.h>
#include <botan/certstor.h>
#include <botan/credentials_manager.h>
using Botan::Credentials_Manager;
/**
* @brief Callbacks invoked by TLS::Channel.
*
* Botan::TLS::Callbacks is an abstract class.
* For improved readability, only the functions that are mandatory
* to implement are listed here. See src/lib/tls/tls_callbacks.h.
*/
class Callbacks: public Botan::TLS::Callbacks {
public:
void tls_emit_data(const uint8_t data[], size_t size) override
{
// send data to tls server, e.g., using BSD sockets or boost asio
}
void tls_record_received(uint64_t seq_no, const uint8_t data[], size_t size)
override
{
// process full TLS record received by tls server, e.g.,
// by passing it to the application
}
void tls_alert(Botan::TLS::Alert alert) override
{
// handle a tls alert received from the tls server
}
bool tls_session_established(const Botan::TLS::Session& session) override
{
// the session with the tls server was established
// return false to prevent the session from being cached, true to
// cache the session in the configured session manager
return false;
}
};
/**
* @brief Credentials storage for the tls client.
*
* It returns a list of trusted CA certificates from a local directory.
* TLS client authentication is disabled. See src/lib/tls/credentials_manager.h.
*/
class Client_Credentials: public Botan::Credentials_Manager {
public:
std::vector<Botan::Certificate_Store*> trusted_certificate_authorities(
const std::string& type, const std::string& context) override
{
// return a list of certificates of CAs we trust for tls server certificates,
// e.g., all the certificates in the local directory "cas"
return {new Botan::Certificate_Store_In_Memory("cas")};
}
std::vector<Botan::X509_Certificate> cert_chain(
const std::vector<std::string>& cert_key_types,
const std::string& type, const std::string& context) override
{
// when using tls client authentication (optional), return
// a certificate chain being sent to the tls server,
// else an empty list
return std::vector<Botan::X509_Certificate>();
}
Botan::Private_Key* private_key_for(const Botan::X509_Certificate& cert,
const std::string& type, const std::string& context) override
{
// when returning a chain in cert_chain(), return the private key
// associated with the leaf certificate here
return nullptr;
}
};
#include <cstdio>
using std::printf;
int main()
{
// prepare all the parameters
Callbacks callbacks;
Botan::AutoSeeded_RNG rng;
Botan::TLS::Session_Manager_In_Memory session_mgr(rng);
Client_Credentials creds;
Botan::TLS::Strict_Policy policy;
const std::vector<uint16_t> acceptable_ciphersuite_list =
policy.ciphersuite_list(Botan::TLS::Protocol_Version::TLS_V12, false);
printf("Cipher suite list:\n");
for (uint16_t id : acceptable_ciphersuite_list)
{
printf("\t0x%04X: %s\n", (int)id, Botan::TLS::Ciphersuite::by_id(id).to_string().c_str());
}
// open the tls connection
Botan::TLS::Client client(callbacks, session_mgr, creds, policy, rng,
Botan::TLS::Server_Information("botan.randombit.net", 443),
Botan::TLS::Protocol_Version::TLS_V12);
while (!client.is_closed()) {
// read data received from the tls server, e.g., using BSD sockets or boost asio
// ...
// send data to the tls server using client.send_data()
// ...
// close TLS channel when we have done everything
client.close();
}
}