Add GetPeerCredentials() to rmi::Gateway
authorSangwan Kwon <sangwan.kwon@samsung.com>
Thu, 16 Jan 2020 09:00:27 +0000 (18:00 +0900)
committer권상완/Security 2Lab(SR)/Engineer/삼성전자 <sangwan.kwon@samsung.com>
Fri, 17 Jan 2020 06:24:01 +0000 (15:24 +0900)
Signed-off-by: Sangwan Kwon <sangwan.kwon@samsung.com>
src/vist/credentials.hpp [new file with mode: 0644]
src/vist/rmi/gateway.cpp
src/vist/rmi/gateway.hpp
src/vist/rmi/impl/credentials.hpp [deleted file]
src/vist/rmi/impl/server.cpp
src/vist/rmi/impl/server.hpp
src/vist/rmi/impl/tests/server-client.cpp
src/vist/rmi/impl/tests/socket.cpp
src/vist/rmi/tests/rmi.cpp

diff --git a/src/vist/credentials.hpp b/src/vist/credentials.hpp
new file mode 100644 (file)
index 0000000..f1ba0c2
--- /dev/null
@@ -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 <vist/exception.hpp>
+
+#include <sys/socket.h>
+#include <sys/types.h>
+
+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
index f12e42dabdc1734362ed0fc3a9c2cdb6cddf0553..5f4bed653866acb5157d4fe4b60ca10e5b1e7bc4 100644 (file)
@@ -84,5 +84,11 @@ void Gateway::stop(void)
        this->pImpl->stop();
 }
 
+/// Credentials exists per thread.
+std::shared_ptr<Credentials> GetPeerCredentials()
+{
+       return Server::GetPeerCredentials();
+}
+
 } // namespace rmi
 } // namespace vist
index d63a816004dd38369bd398a089d22fa477f2fd71..afc7a1a3e0f53efddcaf78c106ee8fd9b973c3ac 100644 (file)
@@ -18,6 +18,7 @@
 
 #define EXPOSE(gateway, object, function) gateway.expose(object, #function, function)
 
+#include <vist/credentials.hpp>
 #include <vist/klass/functor.hpp>
 #include <vist/macro.hpp>
 
@@ -50,6 +51,8 @@ public:
        template<typename O, typename F>
        void expose(O& object, const std::string& name, F&& func);
 
+       static std::shared_ptr<Credentials> GetPeerCredentials();
+
 private:
        class Impl;
 
diff --git a/src/vist/rmi/impl/credentials.hpp b/src/vist/rmi/impl/credentials.hpp
deleted file mode 100644 (file)
index f4af021..0000000
+++ /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 <vist/exception.hpp>
-
-#include <sys/socket.h>
-#include <sys/types.h>
-
-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
index 76abbd1fd0bb47d6206d62f18fd7f18581dd6269..53b1633db95f4622437523fe6aab7c63be9c2208 100644 (file)
@@ -27,6 +27,8 @@ namespace vist {
 namespace rmi {
 namespace impl {
 
+thread_local std::shared_ptr<Credentials> 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));
                });
        };
 
index 1625bd31320e885509e06fef4d0334358da4eb89..a64e09026aa5a933349a4c415787c07655a190b3 100644 (file)
 
 #pragma once
 
+#include <vist/credentials.hpp>
 #include <vist/rmi/gateway.hpp>
-#include <vist/rmi/message.hpp>
 #include <vist/rmi/impl/mainloop.hpp>
 #include <vist/rmi/impl/socket.hpp>
+#include <vist/rmi/message.hpp>
 #include <vist/thread-pool.hpp>
 
 #include <memory>
@@ -48,9 +49,16 @@ public:
        void run(int timeout = -1, Stopper stopper = nullptr);
        void stop(void);
 
+       static std::shared_ptr<Credentials> GetPeerCredentials()
+       {
+               return peer;
+       }
+
 private:
        void accept(const Task& task);
 
+       static thread_local std::shared_ptr<Credentials> peer;
+
        std::unique_ptr<Socket> socket;
        Mainloop mainloop;
        ThreadPool worker;
index a657ed6f533529364510809bd2084ed56057fe6a..2c94b130beffb4360a57eeb6f55d924bec756582 100644 (file)
@@ -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();
+}
index 85d4e25b63bcaf4d5cb734d3fc038e553c818663..54f8e8d4ccbfb3cc94189ffeac00c36a70f11c42 100644 (file)
@@ -14,7 +14,7 @@
  *  limitations under the License
  */
 
-#include <vist/rmi/impl/credentials.hpp>
+#include <vist/credentials.hpp>
 #include <vist/rmi/impl/socket.hpp>
 
 #include <cstring>
@@ -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.
index d39fb4689c49fd5aa8413b8fac237083d93c3189..b0d2fc9d0d0bb289679cc79d69783ae60bc25ab2 100644 (file)
@@ -36,6 +36,9 @@ struct Foo {
 
        std::string getName(void)
        {
+               auto peer = Gateway::GetPeerCredentials();
+               EXPECT_TRUE(peer != nullptr);
+
                return this->name;
        }