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-​2023·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​5 /​/​·​Copyright·​(c)​·​2003-​2023·​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 ··​{60 ··​{
58 ····​if·(!error)​61 ····asio:​:​async_connect(socket_​.​lowest_layer()​,​·endpoints,​
59 ····{62 ········[this](const·std:​:​error_code&·error,​
60 ······socket_.​async_handshake(asio:​:​ssl:​:​stream_base:​:​client,​63 ··········const·tcp:​:​endpoint&·/​*endpoint*/​)​
61 ··········boost:​:​bind(&client:​:​handle_handshake,​·this,​64 ········{
62 ············asio:​:​placeholders:​:​error)​)​;​65 ··········​if·(!error)​
63 ····}66 ··········{
64 ····else67 ············handshake()​;​
65 ····{68 ··········}
66 ······std:​:​cout·<<·"Connect·failed:​·"·<<·error.​message()​·<<·"\n";​69 ··········​else
67 ····}70 ··········{
71 ············​std:​:​cout·​<<·​"Connect·​failed:​·​"·​<<·​error.​message()​·​<<·​"\n";​
72 ··········​}
73 ········​})​;​
68 ··​}74 ··​}
69 75
70 ··​void·handle_handshake(cons​t·asio:​:​error_code&·error)​76 ··​void·​handshake()​
71 ··​{77 ··​{
72 ····if·(!error)​78 ····socket_.​async_handshake(asio:​:​ssl:​:​stream_base:​:​client,​
73 ····{79 ········[this](const·std:​:​error_code&·error)​
74 ······std:​:​cout·<<·"Enter·message:​·";​80 ········{
75 ······std:​:​cin.​getline(request_,​·max_length)​;​81 ··········if·(!error)​
76 ······size_t·request_length·=·strlen(request_)​;​82 ··········{
77 83 ············send_request()​;​
78 ······asio:​:​async_write(socket_,​84 ··········}
79 ··········asio:​:​buffer(request_,​·request_length)​,​85 ··········​else
80 ··········boost:​:​bind(&client:​:​handle_write,​·this,​86 ··········{
81 ············asio:​:​placeholders:​:​error,​87 ············​std:​:​cout·<<·"Handshake·failed:​·"·<<·error.​message()​·<<·"\n";​
82 ············asio:​:​placeholders:​:​bytes_transferred)​)​;​88 ··········}
83 ····​}89 ········​})​;​
84 ····else
85 ····{
86 ······std:​:​cout·<<·"Handshake·failed:​·"·<<·error.​message()​·<<·"\n";​
87 ····}
88 ··​}90 ··​}
89 91
90 ··​void·handle_write(const·asio:​:​error_code&·error,​92 ··​void·send_request()​
91 ······size_t·bytes_transferred)​
92 ··​{93 ··​{
93 ····if·(!error)​94 ····std:​:​cout·<<·"Enter·message:​·";​
94 ····{95 ····std:​:​cin.​getline(request_,​·max_length)​;​
95 ······asio:​:​async_read(socket_,​96 ····size_t·request_length·=·std:​:​strlen(request_)​;​
96 ··········asio:​:​buffer(reply_,​·bytes_transferred)​,​97
97 ··········boost:​:​bind(&client:​:​handle_read,​·this,​98 ····asio:​:​async_write(socket_,​
98 ············​asio:​:​placeholders:​:​error,​99 ········​asio:​:​buffer(request_,​·request_length)​,​
99 ············asio:​:​placeholders:​:​bytes_transferred)​)​;​100 ········[this](const·std:​:​error_code&·error,​·std:​:​size_t·length)​
100 ····}101 ········{
101 ····​else102 ··········if·(!error)​
102 ····​{103 ··········​{
103 ······std:​:​cout·<<·"Write·failed:​·"·<<·error.​message()​·<<·"\n";​104 ············receive_response(leng​th)​;​
104 ····​}105 ··········​}
106 ··········​else
107 ··········​{
108 ············​std:​:​cout·​<<·​"Write·​failed:​·​"·​<<·​error.​message()​·​<<·​"\n";​
109 ··········​}
110 ········​})​;​
105 ··​}111 ··​}
106 112
107 ··​void·handle_read(const·asio:​:​error_code&·error,​113 ··​void·receive_response(std:​:​size_t·length)​
108 ······size_t·bytes_transferred)​
109 ··​{114 ··​{
110 ····​if·(!error)​115 ····asio:​:​async_read(socket_,​
111 ····{116 ········asio:​:​buffer(reply_,​·length)​,​
112 ······​std:​:​cout·<<·"Reply:​·";​117 ········[this](const·​std:​:​error_code&·error,​·std:​:​size_t·length)​
113 ······std:​:​cout.​write(reply_,​·bytes_transferred)​;​118 ········{
114 ······std:​:​cout·<<·"\n";​119 ··········if·(!error)​
115 ····}120 ··········{
116 ····​else121 ············std:​:​cout·<<·"Reply:​·";​
117 ····{122 ············std:​:​cout.​write(reply_,​·length)​;​
118 ······std:​:​cout·<<·"Read·failed:​·"·<<·error.​message()​·​<<·​"\n";​123 ············std:​:​cout·​<<·​"\n";​
119 ····​}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 }