wss_engine.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MPL-2.0 */
2 
3 #include "precompiled.hpp"
4 #include "wss_engine.hpp"
5 
6 static int verify_certificate_callback (gnutls_session_t session)
7 {
8  unsigned int status;
9  const char *hostname;
10 
11  // read hostname
12  hostname = (const char *) gnutls_session_get_ptr (session);
13 
14  int rc = gnutls_certificate_verify_peers3 (session, hostname, &status);
15  zmq_assert (rc >= 0);
16 
17  if (status != 0) {
18  // TODO: somehow log the error
19  // Certificate is not trusted
20  return GNUTLS_E_CERTIFICATE_ERROR;
21  }
22 
23  // notify gnutls to continue handshake normally
24  return 0;
25 }
26 
27 
29  const options_t &options_,
30  const endpoint_uri_pair_t &endpoint_uri_pair_,
31  ws_address_t &address_,
32  bool client_,
33  void *tls_server_cred_,
34  const std::string &hostname_) :
35  ws_engine_t (fd_, options_, endpoint_uri_pair_, address_, client_),
36  _established (false),
37  _tls_client_cred (NULL)
38 {
39  int rc = 0;
40 
41  if (client_) {
42  // TODO: move to session_base, to allow changing the socket options between connect calls
43  rc = gnutls_certificate_allocate_credentials (&_tls_client_cred);
44  zmq_assert (rc == 0);
45 
46  if (options_.wss_trust_system)
47  gnutls_certificate_set_x509_system_trust (_tls_client_cred);
48 
49  if (options_.wss_trust_pem.length () > 0) {
50  gnutls_datum_t trust = {
51  (unsigned char *) options_.wss_trust_pem.c_str (),
52  (unsigned int) options_.wss_trust_pem.length ()};
53  rc = gnutls_certificate_set_x509_trust_mem (
54  _tls_client_cred, &trust, GNUTLS_X509_FMT_PEM);
55  zmq_assert (rc >= 0);
56  }
57 
58  gnutls_certificate_set_verify_function (_tls_client_cred,
60 
61  rc = gnutls_init (&_tls_session, GNUTLS_CLIENT | GNUTLS_NONBLOCK);
62  zmq_assert (rc == GNUTLS_E_SUCCESS);
63 
64  if (!hostname_.empty ())
65  gnutls_server_name_set (_tls_session, GNUTLS_NAME_DNS,
66  hostname_.c_str (), hostname_.size ());
67 
68  gnutls_session_set_ptr (
70  hostname_.empty () ? NULL : const_cast<char *> (hostname_.c_str ()));
71 
72  rc = gnutls_credentials_set (_tls_session, GNUTLS_CRD_CERTIFICATE,
74  zmq_assert (rc == GNUTLS_E_SUCCESS);
75  } else {
76  zmq_assert (tls_server_cred_);
77 
78  rc = gnutls_init (&_tls_session, GNUTLS_SERVER | GNUTLS_NONBLOCK);
79  zmq_assert (rc == GNUTLS_E_SUCCESS);
80 
81  rc = gnutls_credentials_set (_tls_session, GNUTLS_CRD_CERTIFICATE,
82  tls_server_cred_);
83  zmq_assert (rc == GNUTLS_E_SUCCESS);
84  }
85 
86  gnutls_set_default_priority (_tls_session);
87  gnutls_transport_set_int (_tls_session, fd_);
88 }
89 
91 {
92  gnutls_deinit (_tls_session);
93 
94  if (_tls_client_cred)
95  gnutls_certificate_free_credentials (_tls_client_cred);
96 }
97 
99 {
100  set_pollin ();
101  in_event ();
102 }
103 
105 {
106  if (_established)
107  return ws_engine_t::out_event ();
108 
109  do_handshake ();
110 }
111 
113 {
114  int rc = gnutls_handshake (_tls_session);
115 
116  reset_pollout ();
117 
118  if (rc == GNUTLS_E_SUCCESS) {
119  start_ws_handshake ();
120  _established = true;
121  return false;
122  } else if (rc == GNUTLS_E_AGAIN) {
123  int direction = gnutls_record_get_direction (_tls_session);
124  if (direction == 1)
125  set_pollout ();
126 
127  return false;
128  } else if (rc == GNUTLS_E_INTERRUPTED
129  || rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
130  return false;
131  } else {
133  return false;
134  }
135 
136  return true;
137 }
138 
140 {
141  if (!_established) {
142  if (!do_handshake ()) {
143  return false;
144  }
145  }
146 
147  return ws_engine_t::handshake ();
148 }
149 
150 int zmq::wss_engine_t::read (void *data_, size_t size_)
151 {
152  ssize_t rc = gnutls_record_recv (_tls_session, data_, size_);
153 
154  if (rc == GNUTLS_E_REHANDSHAKE) {
155  gnutls_alert_send (_tls_session, GNUTLS_AL_WARNING,
156  GNUTLS_A_NO_RENEGOTIATION);
157  return 0;
158  }
159 
160  if (rc == GNUTLS_E_INTERRUPTED) {
161  errno = EINTR;
162  return -1;
163  }
164 
165  if (rc == GNUTLS_E_AGAIN) {
166  errno = EAGAIN;
167  return -1;
168  }
169 
170  if (rc == 0) {
171  errno = EPIPE;
172  return -1;
173  }
174 
175  if (rc < 0) {
176  errno = EINVAL;
177  return -1;
178  }
179 
180  // TODO: change return type to ssize_t (signed)
181  return rc;
182 }
183 
184 int zmq::wss_engine_t::write (const void *data_, size_t size_)
185 {
186  ssize_t rc = gnutls_record_send (_tls_session, data_, size_);
187 
188  if (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN) {
189  return 0;
190  }
191 
192  if (rc < 0) {
193  errno = EINVAL;
194  return -1;
195  }
196 
197  // TODO: change return type to ssize_t (signed)
198  return rc;
199 }
zmq::ws_engine_t::handshake
bool handshake()
Definition: ws_engine.cpp:233
data_
StringPiece data_
Definition: bytestream_unittest.cc:60
zmq::wss_engine_t::out_event
void out_event()
Definition: wss_engine.cpp:104
zmq::wss_engine_t::write
int write(const void *data_, size_t size_)
Definition: wss_engine.cpp:184
zmq::wss_engine_t::_tls_session
gnutls_session_t _tls_session
Definition: wss_engine.hpp:38
NULL
NULL
Definition: test_security_zap.cpp:405
zmq::options_t
Definition: options.hpp:34
EINTR
#define EINTR
Definition: errno.hpp:7
EINVAL
#define EINVAL
Definition: errno.hpp:25
EAGAIN
#define EAGAIN
Definition: errno.hpp:14
precompiled.hpp
zmq_assert
#define zmq_assert(x)
Definition: err.hpp:102
string
GLsizei const GLchar *const * string
Definition: glcorearb.h:3083
wss_engine.hpp
errno
int errno
zmq::wss_engine_t::wss_engine_t
wss_engine_t(fd_t fd_, const options_t &options_, const endpoint_uri_pair_t &endpoint_uri_pair_, ws_address_t &address_, bool client_, void *tls_server_cred_, const std::string &hostname_)
Definition: wss_engine.cpp:28
error
Definition: cJSON.c:88
zmq::fd_t
int fd_t
Definition: zmq.hpp:287
zmq::wss_engine_t::~wss_engine_t
~wss_engine_t()
Definition: wss_engine.cpp:90
zmq::endpoint_uri_pair_t
Definition: endpoint.hpp:17
zmq::wss_engine_t::_tls_client_cred
gnutls_certificate_credentials_t _tls_client_cred
Definition: wss_engine.hpp:37
zmq::wss_engine_t::read
int read(void *data, size_t size_)
Definition: wss_engine.cpp:150
zmq::stream_engine_base_t::out_event
void out_event() ZMQ_OVERRIDE
Definition: stream_engine_base.cpp:314
zmq::i_engine::connection_error
@ connection_error
Definition: i_engine.hpp:20
verify_certificate_callback
static int verify_certificate_callback(gnutls_session_t session)
Definition: wss_engine.cpp:6
zmq::ws_address_t
Definition: ws_address.hpp:15
zmq::wss_engine_t::handshake
bool handshake()
Definition: wss_engine.cpp:139
zmq::wss_engine_t::do_handshake
bool do_handshake()
Definition: wss_engine.cpp:112
zmq::wss_engine_t::plug_internal
void plug_internal()
Definition: wss_engine.cpp:98
zmq::ws_engine_t
Definition: ws_engine.hpp:100
false
#define false
Definition: cJSON.c:70
options_
DebugStringOptions options_
Definition: src/google/protobuf/descriptor.cc:2410


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:07:02