diff --git a/include/dsn/tool-api/network.h b/include/dsn/tool-api/network.h index 0b3cf6645e..8e630b1af6 100644 --- a/include/dsn/tool-api/network.h +++ b/include/dsn/tool-api/network.h @@ -191,6 +191,11 @@ class connection_oriented_network : public network /*! session managements (both client and server types) */ + +namespace security { +class negotiation; +} + class rpc_client_matcher; class rpc_session : public ref_counter { @@ -227,6 +232,9 @@ class rpc_session : public ref_counter bool delay_recv(int delay_ms); bool on_recv_message(message_ex *msg, int delay_ms); + /// for negotiation + void start_negotiation(); + public: /// /// for subclass to implement receiving message @@ -256,6 +264,7 @@ class rpc_session : public ref_counter enum session_state { SS_CONNECTING, + SS_NEGOTIATING, SS_CONNECTED, SS_DISCONNECTED }; @@ -286,6 +295,7 @@ class rpc_session : public ref_counter bool set_connecting(); // return true when it is permitted bool set_disconnected(); + void set_negotiation(); void set_connected(); void clear_send_queue(bool resend_msgs); @@ -299,11 +309,16 @@ class rpc_session : public ref_counter message_reader _reader; message_parser_ptr _parser; +private: + void auth_negotiation(); + private: const bool _is_client; rpc_client_matcher *_matcher; std::atomic_int _delay_server_receive_ms; + + std::unique_ptr _negotiation; }; // --------- inline implementation -------------- diff --git a/src/runtime/CMakeLists.txt b/src/runtime/CMakeLists.txt index 5ebbeda09d..d369f70f96 100644 --- a/src/runtime/CMakeLists.txt +++ b/src/runtime/CMakeLists.txt @@ -1,9 +1,11 @@ add_subdirectory(test) add_subdirectory(rpc) add_subdirectory(task) +add_subdirectory(security) # TODO(zlw) remove perf_counter from dsn_runtime after the refactor by WuTao add_library(dsn_runtime STATIC + $ $ $ $ diff --git a/src/runtime/rpc/asio_net_provider.cpp b/src/runtime/rpc/asio_net_provider.cpp index 8d2f0fb095..2f1e29e114 100644 --- a/src/runtime/rpc/asio_net_provider.cpp +++ b/src/runtime/rpc/asio_net_provider.cpp @@ -153,6 +153,9 @@ void asio_network_provider::do_accept() null_parser, false); + // start negotiation when server accepts the connection + s->start_negotiation(); + // when server connection threshold is hit, close the session, otherwise accept it if (check_if_conn_threshold_exceeded(s->remote_address())) { dwarn("close rpc connection from %s to %s due to hitting server " diff --git a/src/runtime/rpc/asio_rpc_session.cpp b/src/runtime/rpc/asio_rpc_session.cpp index f68187485c..b18122f985 100644 --- a/src/runtime/rpc/asio_rpc_session.cpp +++ b/src/runtime/rpc/asio_rpc_session.cpp @@ -199,6 +199,10 @@ void asio_rpc_session::connect() dinfo("client session %s connected", _remote_addr.to_string()); set_options(); + + // start auth negotiation when client is connecting to server + start_negotiation(); + set_connected(); on_send_completed(); start_read_next(); diff --git a/src/runtime/rpc/network.cpp b/src/runtime/rpc/network.cpp index d2456790a6..b24760f75a 100644 --- a/src/runtime/rpc/network.cpp +++ b/src/runtime/rpc/network.cpp @@ -24,17 +24,23 @@ * THE SOFTWARE. */ -#include -#include +#include "runtime/security/negotiation.h" #include "message_parser_manager.h" #include "runtime/rpc/rpc_engine.h" +#include +#include + namespace dsn { /*static*/ join_point rpc_session::on_rpc_session_connected("rpc.session.connected"); /*static*/ join_point rpc_session::on_rpc_session_disconnected("rpc.session.disconnected"); +namespace security { +extern bool FLAGS_enable_auth; +} // namespace security + rpc_session::~rpc_session() { clear_send_queue(false); @@ -65,7 +71,9 @@ void rpc_session::set_connected() { utils::auto_lock l(_lock); - dassert(_connect_state == SS_CONNECTING, "session must be connecting"); + dassert((_connect_state == SS_NEGOTIATING && security::FLAGS_enable_auth) || + (_connect_state == SS_CONNECTING && !security::FLAGS_enable_auth), + "wrong session state"); _connect_state = SS_CONNECTED; } @@ -75,6 +83,17 @@ void rpc_session::set_connected() on_rpc_session_connected.execute(this); } +void rpc_session::set_negotiation() +{ + dassert(is_client(), "must be client session"); + + { + utils::auto_lock l(_lock); + dassert(_connect_state == SS_CONNECTING, "session must be connecting"); + _connect_state = SS_NEGOTIATING; + } +} + bool rpc_session::set_disconnected() { { @@ -414,6 +433,24 @@ bool rpc_session::on_recv_message(message_ex *msg, int delay_ms) return true; } +void rpc_session::start_negotiation() +{ + if (security::FLAGS_enable_auth) { + // set the negotiation state if it's a client rpc_session + if (is_client()) { + set_negotiation(); + } + + auth_negotiation(); + } +} + +void rpc_session::auth_negotiation() +{ + _negotiation = security::create_negotiation(is_client(), this); + _negotiation->start_negotiate(); +} + //////////////////////////////////////////////////////////////////////////////////////////////// network::network(rpc_engine *srv, network *inner_provider) : _engine(srv), _client_hdr_format(NET_HDR_DSN), _unknown_msg_header_format(NET_HDR_INVALID) @@ -720,4 +757,5 @@ void connection_oriented_network::on_client_session_disconnected(rpc_session_ptr scount); } } + } // namespace dsn diff --git a/src/runtime/security/CMakeLists.txt b/src/runtime/security/CMakeLists.txt new file mode 100644 index 0000000000..47c08e80c1 --- /dev/null +++ b/src/runtime/security/CMakeLists.txt @@ -0,0 +1,21 @@ +set(MY_PROJ_NAME dsn.security) + +# Source files under CURRENT project directory will be automatically included. +# You can manually set MY_PROJ_SRC to include source files under other directories. +set(MY_PROJ_SRC "") + +# Search mode for source files under CURRENT project directory? +# "GLOB_RECURSE" for recursive search +# "GLOB" for non-recursive search +set(MY_SRC_SEARCH_MODE "GLOB") + +set(MY_PROJ_INC_PATH "") + +set(MY_PROJ_LIBS "") + +set(MY_PROJ_LIB_PATH "") + +# Extra files that will be installed +set(MY_BINPLACES "") + +dsn_add_object() diff --git a/src/runtime/security/client_negotiation.cpp b/src/runtime/security/client_negotiation.cpp new file mode 100644 index 0000000000..52794731c2 --- /dev/null +++ b/src/runtime/security/client_negotiation.cpp @@ -0,0 +1,31 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include "client_negotiation.h" + +namespace dsn { +namespace security { + +client_negotiation::client_negotiation(rpc_session *session) : negotiation(session) {} + +void client_negotiation::start_negotiate() +{ + // TBD(zlw) +} + +} // namespace security +} // namespace dsn diff --git a/src/runtime/security/client_negotiation.h b/src/runtime/security/client_negotiation.h new file mode 100644 index 0000000000..c4ed683cc1 --- /dev/null +++ b/src/runtime/security/client_negotiation.h @@ -0,0 +1,33 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma once + +#include "negotiation.h" + +namespace dsn { +namespace security { + +class client_negotiation : public negotiation +{ +public: + client_negotiation(rpc_session *session); + void start_negotiate(); +}; + +} // namespace security +} // namespace dsn diff --git a/src/runtime/security/negotiation.cpp b/src/runtime/security/negotiation.cpp new file mode 100644 index 0000000000..2cf8f16c3b --- /dev/null +++ b/src/runtime/security/negotiation.cpp @@ -0,0 +1,42 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include "negotiation.h" +#include "client_negotiation.h" +#include "server_negotiation.h" + +#include +#include + +namespace dsn { +namespace security { + +DSN_DEFINE_bool("security", enable_auth, false, "whether open auth or not"); + +negotiation::~negotiation() {} + +std::unique_ptr create_negotiation(bool is_client, rpc_session *session) +{ + if (is_client) { + return make_unique(session); + } else { + return make_unique(session); + } +} + +} // namespace security +} // namespace dsn diff --git a/src/runtime/security/negotiation.h b/src/runtime/security/negotiation.h new file mode 100644 index 0000000000..d7f5c49272 --- /dev/null +++ b/src/runtime/security/negotiation.h @@ -0,0 +1,43 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma once + +#include + +namespace dsn { +class rpc_session; + +namespace security { + +class negotiation +{ +public: + negotiation(rpc_session *session) : _session(session) {} + virtual ~negotiation() = 0; + + virtual void start_negotiate() = 0; + +protected: + // The ownership of the negotiation instance is held by rpc_session. + // So negotiation keeps only a raw pointer. + rpc_session *_session; +}; + +std::unique_ptr create_negotiation(bool is_client, rpc_session *session); +} // namespace security +} // namespace dsn diff --git a/src/runtime/security/server_negotiation.cpp b/src/runtime/security/server_negotiation.cpp new file mode 100644 index 0000000000..cbeb049c32 --- /dev/null +++ b/src/runtime/security/server_negotiation.cpp @@ -0,0 +1,31 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include "server_negotiation.h" + +namespace dsn { +namespace security { + +server_negotiation::server_negotiation(rpc_session *session) : negotiation(session) {} + +void server_negotiation::start_negotiate() +{ + // TBD(zlw) +} + +} // namespace security +} // namespace dsn diff --git a/src/runtime/security/server_negotiation.h b/src/runtime/security/server_negotiation.h new file mode 100644 index 0000000000..197edf3a54 --- /dev/null +++ b/src/runtime/security/server_negotiation.h @@ -0,0 +1,33 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma once + +#include "negotiation.h" + +namespace dsn { +namespace security { + +class server_negotiation : public negotiation +{ +public: + server_negotiation(rpc_session *session); + void start_negotiate(); +}; + +} // namespace security +} // namespace dsn