src/​examples/​cpp03/​ssl/​client.​cppsrc/​examples/​cpp11/​ssl/​client.​cpp
1 /​/​1 /​/​
2 /​/​·​client.​cpp2 /​/​·​client.​cpp
3 /​/​·​~~~~~~~~~~3 /​/​·​~~~~~~~~~~
4 /​/​4 /​/​
5 /​/​·​Copyright·​(c)​·​2003-​2022·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​5 /​/​·​Copyright·​(c)​·​2003-​2022·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​
6 /​/​6 /​/​
7 /​/​·​Distributed·​under·​the·​Boost·​Software·​License,​·​Version·​1.​0.​·​(See·​accompanying7 /​/​·​Distributed·​under·​the·​Boost·​Software·​License,​·​Version·​1.​0.​·​(See·​accompanying
8 /​/​·​file·​LICENSE_1_0.​txt·​or·​copy·​at·​http:​/​/​www.​boost.​org/​LICENSE_1_0.​txt)​8 /​/​·​file·​LICENSE_1_0.​txt·​or·​copy·​at·​http:​/​/​www.​boost.​org/​LICENSE_1_0.​txt)​
9 /​/​9 /​/​
10 10
11 #include·​<cstdlib>11 #include·​<cstdlib>
12 #include·​<cstring>
13 #include·​<functional>
12 #include·​<iostream>14 #include·​<iostream>
13 #include·​<boost/​bind/​bind.​hpp>
14 #include·​"asio.​hpp"15 #include·​"asio.​hpp"
15 #include·​"asio/​ssl.​hpp"16 #include·​"asio/​ssl.​hpp"
16 17
18 using·​asio:​:​ip:​:​tcp;​
19 using·​std:​:​placeholders:​:​_1;​
20 using·​std:​:​placeholders:​:​_2;​
21
17 enum·​{·​max_length·​=·​1024·​};​22 enum·​{·​max_length·​=·​1024·​};​
18 23
19 class·​client24 class·​client
20 {25 {
21 public:​26 public:​
22 ··​client(asio:​:​io_context&·​io_context,​27 ··​client(asio:​:​io_context&·​io_context,​
23 ······​asio:​:​ssl:​:​context&·​context,​28 ······​asio:​:​ssl:​:​context&·​context,​
24 ······asio:​:​ip:​:​tcp:​:​resolver:​:​results_type·​endpoints)​29 ······const·tcp:​:​resolver:​:​results_type&·​endpoints)​
25 ····​:​·​socket_(io_context,​·​context)​30 ····​:​·​socket_(io_context,​·​context)​
26 ··​{31 ··​{
27 ····​socket_.​set_verify_mode(asio:​:​ssl:​:​verify_peer)​;​32 ····​socket_.​set_verify_mode(asio:​:​ssl:​:​verify_peer)​;​
28 ····​socket_.​set_verify_callback(33 ····​socket_.​set_verify_callback(
29 ········boost:​:​bind(&client:​:​verify_certificate,​·​this,​34 ········​std:​:​bind(&client:​:​verify_certificate,​·​this,​·_1,​·_2)​)​;​
30 ··········boost:​:​placeholders:​:​_1,​·boost:​:​placeholders:​:​_2)​)​;​
31 35
32 ····asio:​:​async_connect(socket_​.​lowest_layer()​,​·endpoints,​36 ····​connect(endpoints)​;​
33 ········boost:​:​bind(&client:​:​handle_connect,​·this,​
34 ··········asio:​:​placeholders:​:​error)​)​;​
35 ··​}37 ··​}
36 38
39 private:​
37 ··​bool·​verify_certificate(bo​ol·​preverified,​40 ··​bool·​verify_certificate(bo​ol·​preverified,​
38 ······​asio:​:​ssl:​:​verify_context&·​ctx)​41 ······​asio:​:​ssl:​:​verify_context&·​ctx)​
39 ··​{42 ··​{
40 ····​/​/​·​The·​verify·​callback·​can·​be·​used·​to·​check·​whether·​the·​certificate·​that·​is43 ····​/​/​·​The·​verify·​callback·​can·​be·​used·​to·​check·​whether·​the·​certificate·​that·​is
41 ····​/​/​·​being·​presented·​is·​valid·​for·​the·​peer.​·​For·​example,​·​RFC·​2818·​describes44 ····​/​/​·​being·​presented·​is·​valid·​for·​the·​peer.​·​For·​example,​·​RFC·​2818·​describes
42 ····​/​/​·​the·​steps·​involved·​in·​doing·​this·​for·​HTTPS.​·​Consult·​the·​OpenSSL45 ····​/​/​·​the·​steps·​involved·​in·​doing·​this·​for·​HTTPS.​·​Consult·​the·​OpenSSL
43 ····​/​/​·​documentation·​for·​more·​details.​·​Note·​that·​the·​callback·​is·​called·​once46 ····​/​/​·​documentation·​for·​more·​details.​·​Note·​that·​the·​callback·​is·​called·​once
44 ····​/​/​·​for·​each·​certificate·​in·​the·​certificate·​chain,​·​starting·​from·​the·​root47 ····​/​/​·​for·​each·​certificate·​in·​the·​certificate·​chain,​·​starting·​from·​the·​root
45 ····​/​/​·​certificate·​authority.​48 ····​/​/​·​certificate·​authority.​
46 49
47 ····​/​/​·​In·​this·​example·​we·​will·​simply·​print·​the·​certificate's·​subject·​name.​50 ····​/​/​·​In·​this·​example·​we·​will·​simply·​print·​the·​certificate's·​subject·​name.​
48 ····​char·​subject_name[256];​51 ····​char·​subject_name[256];​
49 ····​X509*·​cert·​=·​X509_STORE_CTX_get_cu​rrent_cert(ctx.​native_handle()​)​;​52 ····​X509*·​cert·​=·​X509_STORE_CTX_get_cu​rrent_cert(ctx.​native_handle()​)​;​
50 ····​X509_NAME_oneline(X50​9_get_subject_name(ce​rt)​,​·​subject_name,​·​256)​;​53 ····​X509_NAME_oneline(X50​9_get_subject_name(ce​rt)​,​·​subject_name,​·​256)​;​
51 ····​std:​:​cout·​<<·​"Verifying·​"·​<<·​subject_name·​<<·​"\n";​54 ····​std:​:​cout·​<<·​"Verifying·​"·​<<·​subject_name·​<<·​"\n";​
52 55
53 ····​return·​preverified;​56 ····​return·​preverified;​
54 ··​}57 ··​}
55 58
56 ··​void·handle_connect(const·asio:​:​error_code&·​error)​59 ··​void·​connect(const·tcp:​:​resolver:​:​results_type&·​endpoints)​
57 ··{
58 ····if·(!error)​
59 ····{
60 ······socket_.​async_handshake(asio:​:​ssl:​:​stream_base:​:​client,​
61 ··········boost:​:​bind(&client:​:​handle_handshake,​·this,​
62 ············asio:​:​placeholders:​:​error)​)​;​
63 ····}
64 ····else
65 ····{
66 ······std:​:​cout·<<·"Connect·failed:​·"·<<·error.​message()​·<<·"\n";​
67 ····}
68 ··}
69
70 ··void·handle_handshake(cons​t·asio:​:​error_code&·error)​
71 ··{
72 ····if·(!error)​
73 ····{
74 ······std:​:​cout·<<·"Enter·message:​·";​
75 ······std:​:​cin.​getline(request_,​·max_length)​;​
76 ······size_t·request_length·=·strlen(request_)​;​
77
78 ······asio:​:​async_write(socket_,​
79 ··········asio:​:​buffer(request_,​·request_length)​,​
80 ··········boost:​:​bind(&client:​:​handle_write,​·this,​
81 ············asio:​:​placeholders:​:​error,​
82 ············asio:​:​placeholders:​:​bytes_transferred)​)​;​
83 ····}
84 ····else
85 ····{
86 ······std:​:​cout·<<·"Handshake·failed:​·"·<<·error.​message()​·<<·"\n";​
87 ····}
88 ··}
89
90 ··void·handle_write(const·asio:​:​error_code&·error,​
91 ······size_t·bytes_transferred)​
92 ··​{60 ··​{
93 ····​if·(!error)​61 ····asio:​:​async_connect(socket_​.​lowest_layer()​,​·endpoints,​
94 ····{62 ········[this](const·std:​:​error_code&·error,​
95 ······asio:​:​async_read(socket_,​63 ··········const·tcp:​:​endpoint&·/​*endpoint*/​)​
96 ··········asio:​:​buffer(reply_,​·bytes_transferred)​,​64 ········{
97 ··········boost:​:​bind(&client:​:​handle_read,​·this,​65 ··········​if·(!error)​
98 ············asio:​:​placeholders:​:​error,​66 ··········{
99 ············asio:​:​placeholders:​:​bytes_transferred)​)​;​67 ············​handshake()​;​
100 ····​}68 ··········​}
101 ····​else69 ··········​else
102 ····​{70 ··········​{
103 ······​std:​:​cout·​<<·​"Write·​failed:​·​"·​<<·​error.​message()​·​<<·​"\n";​71 ············​std:​:​cout·​<<·​"Connect·​failed:​·​"·​<<·​error.​message()​·​<<·​"\n";​
104 ····​}72 ··········​}
105 ··​}73 ········​})​;​
106 74 ··}
107 ··void·handle_read(const·asio:​:​error_code&·error,​75
108 ······size_t·bytes_transferred)​76 ··void·handshake()​
109 ··​{77 ··​{
110 ····if·(!error)​78 ····socket_.​async_handshake(asio:​:​ssl:​:​stream_base:​:​client,​
111 ····{79 ········[this](const·std:​:​error_code&·error)​
112 ······std:​:​cout·<<·"Reply:​·";​80 ········{
113 ······std:​:​cout.​write(reply_,​·bytes_transferred)​;​81 ··········if·(!error)​
114 ······std:​:​cout·<<·"\n";​82 ··········{
115 ····}83 ············send_request()​;​
116 ····else84 ··········}
117 ····{85 ··········else
118 ······std:​:​cout·<<·"Read·failed:​·"·<<·error.​message()​·<<·"\n";​86 ··········{
119 ····}87 ············std:​:​cout·<<·"Handshake·failed:​·"·<<·error.​message()​·<<·"\n";​
88 ··········​}
89 ········​})​;​
90 ··​}
91
92 ··​void·​send_request()​
93 ··​{
94 ····​std:​:​cout·​<<·​"Enter·​message:​·​";​
95 ····​std:​:​cin.​getline(request_,​·​max_length)​;​
96 ····​size_t·​request_length·​=·​std:​:​strlen(request_)​;​
97
98 ····​asio:​:​async_write(socket_,​
99 ········​asio:​:​buffer(request_,​·​request_length)​,​
100 ········​[this](const·​std:​:​error_code&·​error,​·​std:​:​size_t·​length)​
101 ········​{
102 ··········​if·​(!error)​
103 ··········​{
104 ············​receive_response(leng​th)​;​
105 ··········​}
106 ··········​else
107 ··········​{
108 ············​std:​:​cout·​<<·​"Write·​failed:​·​"·​<<·​error.​message()​·​<<·​"\n";​
109 ··········​}
110 ········​})​;​
111 ··​}
112
113 ··​void·​receive_response(std:​:​size_t·​length)​
114 ··​{
115 ····​asio:​:​async_read(socket_,​
116 ········​asio:​:​buffer(reply_,​·​length)​,​
117 ········​[this](const·​std:​:​error_code&·​error,​·​std:​:​size_t·​length)​
118 ········​{
119 ··········​if·​(!error)​
120 ··········​{
121 ············​std:​:​cout·​<<·​"Reply:​·​";​
122 ············​std:​:​cout.​write(reply_,​·​length)​;​
123 ············​std:​:​cout·​<<·​"\n";​
124 ··········​}
125 ··········​else
126 ··········​{
127 ············​std:​:​cout·​<<·​"Read·​failed:​·​"·​<<·​error.​message()​·​<<·​"\n";​
128 ··········​}
129 ········​})​;​
120 ··​}130 ··​}
121 131
122 private:​132 ··asio:​:​ssl:​:​stream<tcp:​:​socket>·socket_;​
123 ··asio:​:​ssl:​:​stream<asio:​:​ip:​:​tcp:​:​socket>·socket_;​
124 ··​char·​request_[max_length];​133 ··​char·​request_[max_length];​
125 ··​char·​reply_[max_length];​134 ··​char·​reply_[max_length];​
126 };​135 };​
127 136
128 int·​main(int·​argc,​·​char*·​argv[])​137 int·​main(int·​argc,​·​char*·​argv[])​
129 {138 {
130 ··​try139 ··​try
131 ··​{140 ··​{
132 ····​if·​(argc·​!=·​3)​141 ····​if·​(argc·​!=·​3)​
133 ····​{142 ····​{
134 ······​std:​:​cerr·​<<·​"Usage:​·​client·​<host>·​<port>\n";​143 ······​std:​:​cerr·​<<·​"Usage:​·​client·​<host>·​<port>\n";​
135 ······​return·​1;​144 ······​return·​1;​
136 ····​}145 ····​}
137 146
138 ····​asio:​:​io_context·​io_context;​147 ····​asio:​:​io_context·​io_context;​
139 148
140 ····asio:​:​ip:​:​tcp:​:​resolver·​resolver(io_context)​;​149 ····​tcp:​:​resolver·​resolver(io_context)​;​
141 ····​asio:​:​ip:​:​tcp:​:​resolver:​:​results_type·endpoints·=150 ····​auto·endpoints·=·resolver.​resolve(argv[1],​·argv[2])​;​
142 ······resolver.​resolve(argv[1],​·argv[2])​;​
143 151
144 ····​asio:​:​ssl:​:​context·​ctx(asio:​:​ssl:​:​context:​:​sslv23)​;​152 ····​asio:​:​ssl:​:​context·​ctx(asio:​:​ssl:​:​context:​:​sslv23)​;​
145 ····​ctx.​load_verify_file("ca.​pem")​;​153 ····​ctx.​load_verify_file("ca.​pem")​;​
146 154
147 ····​client·​c(io_context,​·​ctx,​·​endpoints)​;​155 ····​client·​c(io_context,​·​ctx,​·​endpoints)​;​
148 156
149 ····​io_context.​run()​;​157 ····​io_context.​run()​;​
150 ··​}158 ··​}
151 ··​catch·​(std:​:​exception&·​e)​159 ··​catch·​(std:​:​exception&·​e)​
152 ··​{160 ··​{
153 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​161 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​
154 ··​}162 ··​}
155 163
156 ··​return·​0;​164 ··​return·​0;​
157 }165 }