From: Sangwan Kwon Date: Thu, 16 Jan 2020 09:00:27 +0000 (+0900) Subject: Add GetPeerCredentials() to rmi::Gateway X-Git-Tag: submit/tizen/20200810.073515~93 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a543b0363a834ef5344962f3775e97c6fc92e78a;p=platform%2Fcore%2Fsecurity%2Fvist.git Add GetPeerCredentials() to rmi::Gateway Signed-off-by: Sangwan Kwon --- diff --git a/src/vist/credentials.hpp b/src/vist/credentials.hpp new file mode 100644 index 0000000..f1ba0c2 --- /dev/null +++ b/src/vist/credentials.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020-present Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed 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 + +#include +#include + +namespace vist { + +struct Credentials { + static Credentials Peer(int fd) + { + struct ucred cred; + socklen_t credsz = sizeof(cred); + errno = 0; + if (::getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &credsz)) + THROW(ErrCode::RuntimeError) << "Failed to get peer credential: " << errno; + + return {cred.pid, cred.uid, cred.gid}; + } + + pid_t pid; + uid_t uid; + gid_t gid; +}; + +} // namespace vist diff --git a/src/vist/rmi/gateway.cpp b/src/vist/rmi/gateway.cpp index f12e42d..5f4bed6 100644 --- a/src/vist/rmi/gateway.cpp +++ b/src/vist/rmi/gateway.cpp @@ -84,5 +84,11 @@ void Gateway::stop(void) this->pImpl->stop(); } +/// Credentials exists per thread. +std::shared_ptr GetPeerCredentials() +{ + return Server::GetPeerCredentials(); +} + } // namespace rmi } // namespace vist diff --git a/src/vist/rmi/gateway.hpp b/src/vist/rmi/gateway.hpp index d63a816..afc7a1a 100644 --- a/src/vist/rmi/gateway.hpp +++ b/src/vist/rmi/gateway.hpp @@ -18,6 +18,7 @@ #define EXPOSE(gateway, object, function) gateway.expose(object, #function, function) +#include #include #include @@ -50,6 +51,8 @@ public: template void expose(O& object, const std::string& name, F&& func); + static std::shared_ptr GetPeerCredentials(); + private: class Impl; diff --git a/src/vist/rmi/impl/credentials.hpp b/src/vist/rmi/impl/credentials.hpp deleted file mode 100644 index f4af021..0000000 --- a/src/vist/rmi/impl/credentials.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2020-present Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed 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 - -#include -#include - -namespace vist { -namespace rmi { -namespace impl { - -struct Credentials { - pid_t pid; - uid_t uid; - gid_t gid; - - static Credentials GetPeers(int fd) - { - struct ucred cred; - socklen_t credsz = sizeof(cred); - errno = 0; - if (::getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &credsz)) - THROW(ErrCode::RuntimeError) << "Failed to get peer credential: " << errno; - - return {cred.pid, cred.uid, cred.gid}; - } -}; - -} // namespace impl -} // namespace rmi -} // namespace vist diff --git a/src/vist/rmi/impl/server.cpp b/src/vist/rmi/impl/server.cpp index 76abbd1..53b1633 100644 --- a/src/vist/rmi/impl/server.cpp +++ b/src/vist/rmi/impl/server.cpp @@ -27,6 +27,8 @@ namespace vist { namespace rmi { namespace impl { +thread_local std::shared_ptr Server::peer = nullptr; + Server::Server(const std::string& path, const Task& task, ServiceType type) : worker(5) { switch (type) { @@ -62,6 +64,8 @@ void Server::accept(const Task& task) /// process task per thread this->worker.submit([this, connection, task]{ auto onRead = [connection, task]() { + Server::peer.reset(new Credentials(Credentials::Peer(connection->getFd()))); + Message request = connection->recv(); DEBUG(VIST) << "Session header: " << request.signature; @@ -80,8 +84,7 @@ void Server::accept(const Task& task) this->mainloop.removeHandler(connection->getFd()); }; - this->mainloop.addHandler(connection->getFd(), - std::move(onRead), std::move(onClose)); + this->mainloop.addHandler(connection->getFd(), std::move(onRead), std::move(onClose)); }); }; diff --git a/src/vist/rmi/impl/server.hpp b/src/vist/rmi/impl/server.hpp index 1625bd3..a64e090 100644 --- a/src/vist/rmi/impl/server.hpp +++ b/src/vist/rmi/impl/server.hpp @@ -16,10 +16,11 @@ #pragma once +#include #include -#include #include #include +#include #include #include @@ -48,9 +49,16 @@ public: void run(int timeout = -1, Stopper stopper = nullptr); void stop(void); + static std::shared_ptr GetPeerCredentials() + { + return peer; + } + private: void accept(const Task& task); + static thread_local std::shared_ptr peer; + std::unique_ptr socket; Mainloop mainloop; ThreadPool worker; diff --git a/src/vist/rmi/impl/tests/server-client.cpp b/src/vist/rmi/impl/tests/server-client.cpp index a657ed6..2c94b13 100644 --- a/src/vist/rmi/impl/tests/server-client.cpp +++ b/src/vist/rmi/impl/tests/server-client.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2019-present Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,7 +44,7 @@ std::string response3 = "response argument"; TEST(ServerClientTests, not_ondemand) { - std::string sockPath = "./vist-test.sock"; + std::string sockPath = "@vist-test.sock"; auto task = [&](Message& message) -> Message { EXPECT_EQ(message.signature, requestSignature); @@ -97,3 +97,50 @@ TEST(ServerClientTests, not_ondemand) if (serverThread.joinable()) serverThread.join(); } + +TEST(ServerClientTests, peer_pid) +{ + std::string sockPath = "@vist-test.sock"; + auto task = [](Message& message) -> Message { + EXPECT_EQ(message.signature, requestSignature); + + auto peer = Server::GetPeerCredentials(); + EXPECT_TRUE(peer != nullptr); + + int recv1; + message.disclose(recv1); + EXPECT_EQ(request1, recv1); + + Message reply(Message::Type::Reply, responseSignature); + reply.enclose(response1); + return reply; + }; + + Server server(sockPath, task); + auto serverThread = std::thread([&]() { + server.run(); + }); + + { /// Client configuration + auto clientClosure = [&]() { + Client client(sockPath); + + Message message(Message::Type::MethodCall, requestSignature); + message.enclose(request1); + + auto reply = client.request(message); + EXPECT_EQ(reply.signature, responseSignature); + + int recv1; + reply.disclose(recv1); + EXPECT_EQ(response1, recv1); + }; + + clientClosure(); + } + + server.stop(); + + if (serverThread.joinable()) + serverThread.join(); +} diff --git a/src/vist/rmi/impl/tests/socket.cpp b/src/vist/rmi/impl/tests/socket.cpp index 85d4e25..54f8e8d 100644 --- a/src/vist/rmi/impl/tests/socket.cpp +++ b/src/vist/rmi/impl/tests/socket.cpp @@ -14,7 +14,7 @@ * limitations under the License */ -#include +#include #include #include @@ -109,7 +109,7 @@ TEST(SocketTests, peer_credeintials) Socket accepted = socket.accept(); - auto cred = Credentials::GetPeers(accepted.getFd()); + auto cred = vist::Credentials::Peer(accepted.getFd()); EXPECT_TRUE(cred.pid > 0); // Recv input from client. diff --git a/src/vist/rmi/tests/rmi.cpp b/src/vist/rmi/tests/rmi.cpp index d39fb46..b0d2fc9 100644 --- a/src/vist/rmi/tests/rmi.cpp +++ b/src/vist/rmi/tests/rmi.cpp @@ -36,6 +36,9 @@ struct Foo { std::string getName(void) { + auto peer = Gateway::GetPeerCredentials(); + EXPECT_TRUE(peer != nullptr); + return this->name; }