OpenSDN source code
ovsdb_client_ssl.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <boost/bind/bind.hpp>
6 #include <base/logging.h>
7 
8 #include <oper/agent_sandesh.h>
9 #include <ovsdb_types.h>
10 #include <ovsdb_client_ssl.h>
12 
14 
15 using namespace boost::placeholders;
16 
22 
23 OvsdbClientSsl::OvsdbClientSsl(Agent *agent, IpAddress tor_ip, int tor_port,
24  IpAddress tsn_ip, int keepalive_interval,
25  int ha_stale_route_interval,
26  const std::string &ssl_cert,
27  const std::string &ssl_privkey,
28  const std::string &ssl_cacert,
29  OvsPeerManager *manager) :
30  SslServer(agent->event_manager(), boost::asio::ssl::context::tlsv1_server),
31  OvsdbClient(manager, keepalive_interval, ha_stale_route_interval),
32  agent_(agent), ssl_server_port_(tor_port), tsn_ip_(tsn_ip.to_v4()),
33  shutdown_(false) {
34  // Get SSL context from base class and update
35  boost::asio::ssl::context *ctx = context();
36  boost::system::error_code ec;
37 
38  // Verify peer to have a valid certificate
39  ctx->set_verify_mode((boost::asio::ssl::verify_peer |
40  boost::asio::ssl::verify_fail_if_no_peer_cert), ec);
41  assert(ec.value() == 0);
42 
43  ctx->use_certificate_chain_file(ssl_cert, ec);
44  if (ec.value() != 0) {
45  LOG(ERROR, "Error : " << ec.message() << ", while using cert file : "
46  << ssl_cert);
47  exit(EINVAL);
48  }
49 
50  ctx->use_private_key_file(ssl_privkey, boost::asio::ssl::context::pem, ec);
51  if (ec.value() != 0) {
52  LOG(ERROR, "Error : " << ec.message() << ", while using privkey file : "
53  << ssl_privkey);
54  exit(EINVAL);
55  }
56 
57  ctx->load_verify_file(ssl_cacert, ec);
58  if (ec.value() != 0) {
59  LOG(ERROR, "Error : " << ec.message() << ", while using cacert file : "
60  << ssl_cacert);
61  exit(EINVAL);
62  }
63 }
64 
66 }
67 
71 }
72 
75  this, socket);
76  session->set_observer(boost::bind(&OvsdbClientSsl::OnSessionEvent,
77  this, _1, _2));
78  return session;
79 }
80 
82  TcpSession::Event event) {
83  OvsdbClientSslSession *ssl = static_cast<OvsdbClientSslSession *>(session);
84  ssl->EnqueueEvent(event);
85 }
86 
87 const std::string OvsdbClientSsl::protocol() {
88  return "PSSL";
89 }
90 
91 const std::string OvsdbClientSsl::server() {
92  return LocalEndpoint().address().to_string();
93 }
94 
96  return LocalEndpoint().port();
97 }
98 
100  return tsn_ip_;
101 }
102 
104  if (shutdown_)
105  return;
106  shutdown_ = true;
107  OvsdbClientSslSession *ssl =
108  static_cast<OvsdbClientSslSession *>(NextSession(NULL));
109  while (ssl != NULL) {
110  if (!ssl->IsClosed()) {
111  ssl->TriggerClose();
112  }
113  ssl = static_cast<OvsdbClientSslSession *>(NextSession(ssl));
114  }
115 }
116 
118  SessionKey key(ip, port);
119  SessionMap::iterator it;
120  if (port != 0) {
121  it = session_map_.find(key);
122  } else {
123  it = session_map_.upper_bound(key);
124  }
125  if (it != session_map_.end() && it->first.first == ip) {
126  return it->second;
127  }
128  return NULL;
129 }
130 
132  SessionMap::iterator it;
133  if (session == NULL) {
134  it = session_map_.begin();
135  } else {
136  OvsdbClientSslSession *ssl =
137  static_cast<OvsdbClientSslSession *>(session);
138  SessionKey key(ssl->remote_endpoint().address().to_v4(),
139  ssl->remote_endpoint().port());
140  it = session_map_.upper_bound(key);
141  }
142  if (it != session_map_.end()) {
143  return it->second;
144  }
145  return NULL;
146 }
147 
148 void OvsdbClientSsl::AddSessionInfo(SandeshOvsdbClient &client) {
149  SandeshOvsdbClientSession session;
150  std::vector<SandeshOvsdbClientSession> session_list;
151  OvsdbClientSslSession *ssl = static_cast<OvsdbClientSslSession *>(NextSession(NULL));
152  while (ssl != NULL) {
153  ssl->AddSessionInfo(session);
154  session_list.push_back(session);
155  ssl = static_cast<OvsdbClientSslSession *>(NextSession(ssl));
156  }
157  client.set_sessions(session_list);
158 }
159 
160 // AcceptSession callback from SSLserver, to accept a session
162  if (shutdown_) {
163  // don't accept session while shutting down
164  return false;
165  }
166  return true;
167 }
168 
170  OvsPeerManager *manager, OvsdbClientSsl *server, SslSocket *sock,
171  bool async_ready) : OvsdbClientSession(agent, manager),
172  SslSession(server, sock, async_ready), status_("Init") {
173 
175  boost::bind(&OvsdbClientSslSession::RecvMsg, this, _1, _2));
176 
177  // Process session events in KSync workqueue task context,
179  agent->task_scheduler()->GetTaskId("Agent::KSync"), 0,
180  boost::bind(&OvsdbClientSslSession::ProcessSessionEvent, this, _1));
181  session_event_queue_->set_name("OVSDB ssl session event queue");
182 }
183 
185  delete reader_;
187  delete session_event_queue_;
188 }
189 
191  reader_->OnRead(buffer);
192 }
193 
194 void OvsdbClientSslSession::SendMsg(u_int8_t *buf, std::size_t len) {
195  OVSDB_PKT_TRACE(Trace, "Sending: " + std::string((char *)buf, len));
196  Send(buf, len, NULL);
197 }
198 
199 bool OvsdbClientSslSession::RecvMsg(const u_int8_t *buf, std::size_t len) {
200  OVSDB_PKT_TRACE(Trace, "Received: " + std::string((const char*)buf, len));
201  MessageProcess(buf, len);
202  return true;
203 }
204 
206  OvsdbClientSsl *ovs_server = static_cast<OvsdbClientSsl *>(server());
207  return ovs_server->keepalive_interval();
208 }
209 
210 const boost::system::error_code &
212  return close_reason();
213 }
214 
216  OvsdbClientSsl *ovs_server = static_cast<OvsdbClientSsl *>(server());
217  return ovs_server->connection_table();
218 }
219 
221  OvsdbClientSsl *ovs_server = static_cast<OvsdbClientSsl *>(server());
222  return ovs_server->ksync_obj_manager();
223 }
224 
226  OvsdbClientSsl *ovs_server = static_cast<OvsdbClientSsl *>(server());
227  return ovs_server->tsn_ip();
228 }
229 
231  OvsdbClientSsl *ovs_server = static_cast<OvsdbClientSsl *>(server());
232  ovs_server->DeleteSession(this);
233 }
234 
236  // Close the session and return
237  Close();
238 
239  // SSL session will not notify event for self closed session
240  // generate explicit event
242 }
243 
245  return remote_endpoint().address().to_v4();
246 }
247 
249  return remote_endpoint().port();
250 }
251 
253  boost::system::error_code ec;
254  switch (ovs_event.event) {
255  case TcpSession::CLOSE:
256  {
257  OvsdbClientSsl *ovs_server =
258  static_cast<OvsdbClientSsl *>(server());
259  boost::asio::ip::tcp::endpoint ep = remote_endpoint();
260  OvsdbClientSsl::SessionKey key(ep.address().to_v4(), ep.port());
261  ovs_server->session_map_.erase(key);
262 
263  OnClose();
264  }
265  break;
266  case TcpSession::ACCEPT:
267  {
268  OvsdbClientSsl *ovs_server =
269  static_cast<OvsdbClientSsl *>(server());
270  boost::asio::ip::tcp::endpoint ep = remote_endpoint();
271  OvsdbClientSsl::SessionKey key(ep.address().to_v4(), ep.port());
272  std::pair<OvsdbClientSsl::SessionMap::iterator, bool> ret =
273  ovs_server->session_map_.insert
274  (std::pair<OvsdbClientSsl::SessionKey,
275  OvsdbClientSslSession *>(key, this));
276  // assert if entry already exists
277  assert(ret.second == true);
278  }
279  set_status("Established");
280  OnEstablish();
281  break;
282  default:
283  assert(false);
284  break;
285  }
286  return true;
287 }
288 
290  OvsdbSessionEvent ovs_event;
291  ovs_event.event = event;
292  session_event_queue_->Enqueue(ovs_event);
293 }
294 
boost::asio::ip::address IpAddress
Definition: address.h:13
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
Definition: agent.h:360
TaskScheduler * task_scheduler() const
Definition: agent.h:1122
void AddSessionInfo(SandeshOvsdbClientSession &session)
void MessageProcess(const u_int8_t *buf, std::size_t len)
WorkQueue< OvsdbSessionEvent > * session_event_queue_
void EnqueueEvent(TcpSession::Event event)
OvsdbClientSslSession(Agent *agent, OvsPeerManager *manager, OvsdbClientSsl *server, SslSocket *sock, bool async_ready=true)
void SendMsg(u_int8_t *buf, std::size_t len)
KSyncObjectManager * ksync_obj_manager()
bool RecvMsg(const u_int8_t *buf, std::size_t len)
ConnectionStateTable * connection_table()
virtual void OnRead(Buffer buffer)
const boost::system::error_code & ovsdb_close_reason() const
virtual Ip4Address remote_ip() const
virtual uint16_t remote_port() const
bool ProcessSessionEvent(OvsdbSessionEvent event)
OvsdbClientTcpSessionReader * reader_
void set_status(std::string status)
void OnSessionEvent(TcpSession *session, TcpSession::Event event)
bool AcceptSession(TcpSession *session)
void AddSessionInfo(SandeshOvsdbClient &client)
const std::string protocol()
std::pair< Ip4Address, uint16_t > SessionKey
OvsdbClientSession * NextSession(OvsdbClientSession *session)
virtual SslSession * AllocSession(SslSocket *socket)
const std::string server()
OvsdbClientSession * FindSession(Ip4Address ip, uint16_t port)
friend class OvsdbClientSslSession
OvsPeerManager * peer_manager_
Definition: ovsdb_client.h:64
ConnectionStateTable * connection_table()
Definition: ovsdb_client.cc:40
void RegisterConnectionTable(Agent *agent)
Definition: ovsdb_client.cc:36
int keepalive_interval() const
Definition: ovsdb_client.cc:48
KSyncObjectManager * ksync_obj_manager()
Definition: ovsdb_client.cc:44
boost::asio::ssl::stream< boost::asio::ip::tcp::socket > SslSocket
Definition: ssl_server.h:16
boost::asio::ssl::context * context()
Definition: ssl_server.cc:43
boost::asio::ssl::stream< boost::asio::ip::tcp::socket > SslSocket
Definition: ssl_session.h:20
int GetTaskId(const std::string &name)
Definition: task.cc:861
virtual void OnRead(Buffer buffer)
Definition: tcp_session.cc:672
Endpoint LocalEndpoint() const
Definition: tcp_server.cc:308
virtual bool Initialize(unsigned short port)
Definition: tcp_server.cc:60
virtual void DeleteSession(TcpSession *session)
Definition: tcp_server.cc:199
TcpServer * server()
Definition: tcp_session.h:84
const boost::system::error_code & close_reason() const
Definition: tcp_session.h:141
bool IsClosed() const
Definition: tcp_session.h:121
void set_observer(EventObserver observer)
Definition: tcp_session.cc:219
Endpoint remote_endpoint() const
Definition: tcp_session.h:131
boost::asio::const_buffer Buffer
Definition: tcp_session.h:60
virtual bool Send(const uint8_t *data, size_t size, size_t *sent)
Definition: tcp_session.cc:429
void Close()
Definition: tcp_session.cc:355
Definition: trace.h:288
bool Enqueue(QueueEntryT entry)
Definition: queue_task.h:248
void Shutdown(bool delete_entries=true)
Definition: queue_task.h:152
void set_name(const std::string &name)
Definition: queue_task.h:307
#define LOG(_Level, _Msg)
Definition: logging.h:34
#define OVSDB_PKT_TRACE(obj,...)