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-​2018·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​5 /​/​·​Copyright·​(c)​·​2003-​2018·​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.​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,​·​_1,​·​_2)​)​;​34 ········​std:​:​bind(&client:​:​verify_certificate,​·​this,​·​_1,​·​_2)​)​;​
30 35
31 ····asio:​:​async_connect(socket_​.​lowest_layer()​,​·endpoints,​36 ····​connect(endpoints)​;​
32 ········boost:​:​bind(&client:​:​handle_connect,​·this,​
33 ··········asio:​:​placeholders:​:​error)​)​;​
34 ··​}37 ··​}
35 38
39 private:​
36 ··​bool·​verify_certificate(bo​ol·​preverified,​40 ··​bool·​verify_certificate(bo​ol·​preverified,​
37 ······​asio:​:​ssl:​:​verify_context&·​ctx)​41 ······​asio:​:​ssl:​:​verify_context&·​ctx)​
38 ··​{42 ··​{
39 ····​/​/​·​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
40 ····​/​/​·​being·​presented·​is·​valid·​for·​the·​peer.​·​For·​example,​·​RFC·​2818·​describes44 ····​/​/​·​being·​presented·​is·​valid·​for·​the·​peer.​·​For·​example,​·​RFC·​2818·​describes
41 ····​/​/​·​the·​steps·​involved·​in·​doing·​this·​for·​HTTPS.​·​Consult·​the·​OpenSSL45 ····​/​/​·​the·​steps·​involved·​in·​doing·​this·​for·​HTTPS.​·​Consult·​the·​OpenSSL
42 ····​/​/​·​documentation·​for·​more·​details.​·​Note·​that·​the·​callback·​is·​called·​once46 ····​/​/​·​documentation·​for·​more·​details.​·​Note·​that·​the·​callback·​is·​called·​once
43 ····​/​/​·​for·​each·​certificate·​in·​the·​certificate·​chain,​·​starting·​from·​the·​root47 ····​/​/​·​for·​each·​certificate·​in·​the·​certificate·​chain,​·​starting·​from·​the·​root
44 ····​/​/​·​certificate·​authority.​48 ····​/​/​·​certificate·​authority.​
45 49
46 ····​/​/​·​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.​
47 ····​char·​subject_name[256];​51 ····​char·​subject_name[256];​
48 ····​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()​)​;​
49 ····​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)​;​
50 ····​std:​:​cout·​<<·​"Verifying·​"·​<<·​subject_name·​<<·​"\n";​54 ····​std:​:​cout·​<<·​"Verifying·​"·​<<·​subject_name·​<<·​"\n";​
51 55
52 ····​return·​preverified;​56 ····​return·​preverified;​
53 ··​}57 ··​}
54 58
55 ··​void·handle_connect(const·asio:​:​error_code&·​error)​59 ··​void·​connect(const·tcp:​:​resolver:​:​results_type&·​endpoints)​
56 ··{
57 ····if·(!error)​
58 ····{
59 ······socket_.​async_handshake(asio:​:​ssl:​:​stream_base:​:​client,​
60 ··········boost:​:​bind(&client:​:​handle_handshake,​·this,​
61 ············asio:​:​placeholders:​:​error)​)​;​
62 ····}
63 ····else
64 ····{
65 ······std:​:​cout·<<·"Connect·failed:​·"·<<·error.​message()​·<<·"\n";​
66 ····}
67 ··}
68
69 ··void·handle_handshake(cons​t·asio:​:​error_code&·error)​
70 ··{
71 ····if·(!error)​
72 ····{
73 ······std:​:​cout·<<·"Enter·message:​·";​
74 ······std:​:​cin.​getline(request_,​·max_length)​;​
75 ······size_t·request_length·=·strlen(request_)​;​
76
77 ······asio:​:​async_write(socket_,​
78 ··········asio:​:​buffer(request_,​·request_length)​,​
79 ··········boost:​:​bind(&client:​:​handle_write,​·this,​
80 ············asio:​:​placeholders:​:​error,​
81 ············asio:​:​placeholders:​:​bytes_transferred)​)​;​
82 ····}
83 ····else
84 ····{
85 ······std:​:​cout·<<·"Handshake·failed:​·"·<<·error.​message()​·<<·"\n";​
86 ····}
87 ··}
88
89 ··void·handle_write(const·asio:​:​error_code&·error,​
90 ······size_t·bytes_transferred)​
91 ··​{60 ··​{
92 ····​if·(!error)​61 ····asio:​:​async_connect(socket_​.​lowest_layer()​,​·endpoints,​
93 ····{62 ········[this](const·std:​:​error_code&·error,​
94 ······asio:​:​async_read(socket_,​63 ··········const·tcp:​:​endpoint&·/​*endpoint*/​)​
95 ··········asio:​:​buffer(reply_,​·bytes_transferred)​,​64 ········{
96 ··········boost:​:​bind(&client:​:​handle_read,​·this,​65 ··········​if·(!error)​
97 ············asio:​:​placeholders:​:​error,​66 ··········{
98 ············asio:​:​placeholders:​:​bytes_transferred)​)​;​67 ············​handshake()​;​
99 ····​}68 ··········​}
100 ····​else69 ··········​else
101 ····​{70 ··········​{
102 ······​std:​:​cout·​<<·​"Write·​failed:​·​"·​<<·​error.​message()​·​<<·​"\n";​71 ············​std:​:​cout·​<<·​"Connect·​failed:​·​"·​<<·​error.​message()​·​<<·​"\n";​
103 ····​}72 ··········​}
104 ··​}73 ········​})​;​
105 74 ··}
106 ··void·handle_read(const·asio:​:​error_code&·error,​75
107 ······size_t·bytes_transferred)​76 ··void·handshake()​
108 ··​{77 ··​{
109 ····if·(!error)​78 ····socket_.​async_handshake(asio:​:​ssl:​:​stream_base:​:​client,​
110 ····{79 ········[this](const·std:​:​error_code&·error)​
111 ······std:​:​cout·<<·"Reply:​·";​80 ········{
112 ······std:​:​cout.​write(reply_,​·bytes_transferred)​;​81 ··········if·(!error)​
113 ······std:​:​cout·<<·"\n";​82 ··········{
114 ····}83 ············send_request()​;​
115 ····else84 ··········}
116 ····{85 ··········else
117 ······std:​:​cout·<<·"Read·failed:​·"·<<·error.​message()​·<<·"\n";​86 ··········{
118 ····}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 ········​})​;​
119 ··​}130 ··​}
120 131
121 private:​132 ··asio:​:​ssl:​:​stream<tcp:​:​socket>·socket_;​
122 ··asio:​:​ssl:​:​stream<asio:​:​ip:​:​tcp:​:​socket>·socket_;​
123 ··​char·​request_[max_length];​133 ··​char·​request_[max_length];​
124 ··​char·​reply_[max_length];​134 ··​char·​reply_[max_length];​
125 };​135 };​
126 136
127 int·​main(int·​argc,​·​char*·​argv[])​137 int·​main(int·​argc,​·​char*·​argv[])​
128 {138 {
129 ··​try139 ··​try
130 ··​{140 ··​{
131 ····​if·​(argc·​!=·​3)​141 ····​if·​(argc·​!=·​3)​
132 ····​{142 ····​{
133 ······​std:​:​cerr·​<<·​"Usage:​·​client·​<host>·​<port>\n";​143 ······​std:​:​cerr·​<<·​"Usage:​·​client·​<host>·​<port>\n";​
134 ······​return·​1;​144 ······​return·​1;​
135 ····​}145 ····​}
136 146
137 ····​asio:​:​io_context·​io_context;​147 ····​asio:​:​io_context·​io_context;​
138 148
139 ····asio:​:​ip:​:​tcp:​:​resolver·​resolver(io_context)​;​149 ····​tcp:​:​resolver·​resolver(io_context)​;​
140 ····​asio:​:​ip:​:​tcp:​:​resolver:​:​results_type·endpoints·=150 ····​auto·endpoints·=·resolver.​resolve(argv[1],​·argv[2])​;​
141 ······resolver.​resolve(argv[1],​·argv[2])​;​
142 151
143 ····​asio:​:​ssl:​:​context·​ctx(asio:​:​ssl:​:​context:​:​sslv23)​;​152 ····​asio:​:​ssl:​:​context·​ctx(asio:​:​ssl:​:​context:​:​sslv23)​;​
144 ····​ctx.​load_verify_file("ca.​pem")​;​153 ····​ctx.​load_verify_file("ca.​pem")​;​
145 154
146 ····​client·​c(io_context,​·​ctx,​·​endpoints)​;​155 ····​client·​c(io_context,​·​ctx,​·​endpoints)​;​
147 156
148 ····​io_context.​run()​;​157 ····​io_context.​run()​;​
149 ··​}158 ··​}
150 ··​catch·​(std:​:​exception&·​e)​159 ··​catch·​(std:​:​exception&·​e)​
151 ··​{160 ··​{
152 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​161 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​
153 ··​}162 ··​}
154 163
155 ··​return·​0;​164 ··​return·​0;​
156 }165 }