From 9703e341cc614b519a3a57d9356c6e8d3ca2cc1a Mon Sep 17 00:00:00 2001 From: Lukasz Kostyra Date: Mon, 17 Nov 2014 12:48:55 +0100 Subject: [PATCH] Extract communication functions to common library Since slave service will use the same functions as client library to send data, these are extracted in this commit and will be used in the next change. [Verification] Build, install, run tests. Change-Id: I4b9e11015c657066657f493e87d68958283bb947 --- src/client/client-common.cpp | 211 -------------------------- src/client/client-offline.cpp | 3 +- src/client/client-security-manager.cpp | 2 + src/client/include/client-common.h | 21 --- src/common/CMakeLists.txt | 1 + src/common/connection.cpp | 261 +++++++++++++++++++++++++++++++++ src/common/include/connection.h | 57 +++++++ src/server/service/service.cpp | 1 + 8 files changed, 324 insertions(+), 233 deletions(-) create mode 100644 src/common/connection.cpp create mode 100644 src/common/include/connection.h diff --git a/src/client/client-common.cpp b/src/client/client-common.cpp index 883ab8d..3051cbc 100644 --- a/src/client/client-common.cpp +++ b/src/client/client-common.cpp @@ -45,225 +45,14 @@ IMPLEMENT_SAFE_SINGLETON(SecurityManager::Log::LogSystem); namespace { -const int POLL_TIMEOUT = -1; - void securityClientEnableLogSystem(void) { SecurityManager::Singleton::Instance().SetTag("SECURITY_MANAGER_CLIENT"); } -int waitForSocket(int sock, int event, int timeout) { - int retval; - pollfd desc[1]; - desc[0].fd = sock; - desc[0].events = event; - - while((-1 == (retval = poll(desc, 1, timeout))) && (errno == EINTR)) { - timeout >>= 1; - errno = 0; - } - - if (0 == retval) { - LogDebug("Poll timeout"); - } else if (-1 == retval) { - int err = errno; - LogError("Error in poll: " << strerror(err)); - } - return retval; -} - -class SockRAII { -public: - SockRAII() - : m_sock(-1) - {} - - virtual ~SockRAII() { - if (m_sock > -1) - close(m_sock); - } - - int Connect(char const * const interface) { - sockaddr_un clientAddr; - int flags; - - if (m_sock != -1) // guard - close(m_sock); - - m_sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (m_sock < 0) { - int err = errno; - LogError("Error creating socket: " << strerror(err)); - return SECURITY_MANAGER_API_ERROR_SOCKET; - } - - if ((flags = fcntl(m_sock, F_GETFL, 0)) < 0 || - fcntl(m_sock, F_SETFL, flags | O_NONBLOCK) < 0) - { - int err = errno; - LogError("Error in fcntl: " << strerror(err)); - return SECURITY_MANAGER_API_ERROR_SOCKET; - } - - memset(&clientAddr, 0, sizeof(clientAddr)); - - clientAddr.sun_family = AF_UNIX; - - if (strlen(interface) >= sizeof(clientAddr.sun_path)) { - LogError("Error: interface name " << interface << "is too long. Max len is:" << sizeof(clientAddr.sun_path)); - return SECURITY_MANAGER_API_ERROR_NO_SUCH_SERVICE; - } - - strcpy(clientAddr.sun_path, interface); - - LogDebug("ClientAddr.sun_path = " << interface); - - int retval = TEMP_FAILURE_RETRY(connect(m_sock, (struct sockaddr*)&clientAddr, SUN_LEN(&clientAddr))); - if ((retval == -1) && (errno == EINPROGRESS)) { - if (0 >= waitForSocket(m_sock, POLLOUT, POLL_TIMEOUT)) { - LogError("Error in waitForSocket."); - return SECURITY_MANAGER_API_ERROR_SOCKET; - } - int error = 0; - socklen_t len = sizeof(error); - retval = getsockopt(m_sock, SOL_SOCKET, SO_ERROR, &error, &len); - - if (-1 == retval) { - int err = errno; - LogError("Error in getsockopt: " << strerror(err)); - return SECURITY_MANAGER_API_ERROR_SOCKET; - } - - if (error == EACCES) { - LogError("Access denied"); - return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED; - } - - if (error != 0) { - LogError("Error in connect: " << strerror(error)); - return SECURITY_MANAGER_API_ERROR_SOCKET; - } - - return SECURITY_MANAGER_API_SUCCESS; - } - - if (-1 == retval) { - int err = errno; - LogError("Error connecting socket: " << strerror(err)); - if (err == EACCES) - return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED; - if (err == ENOTSOCK) - return SECURITY_MANAGER_API_ERROR_NO_SUCH_SERVICE; - return SECURITY_MANAGER_API_ERROR_SOCKET; - } - - return SECURITY_MANAGER_API_SUCCESS; - } - - int Get() { - return m_sock; - } - -private: - int m_sock; -}; - } // namespace anonymous namespace SecurityManager { -int sendToServer(char const * const interface, const RawBuffer &send, MessageBuffer &recv) { - int ret; - SockRAII sock; - ssize_t done = 0; - char buffer[2048]; - - if (SECURITY_MANAGER_API_SUCCESS != (ret = sock.Connect(interface))) { - LogError("Error in SockRAII"); - return ret; - } - - while ((send.size() - done) > 0) { - if (0 >= waitForSocket(sock.Get(), POLLOUT, POLL_TIMEOUT)) { - LogError("Error in poll(POLLOUT)"); - return SECURITY_MANAGER_API_ERROR_SOCKET; - } - ssize_t temp = TEMP_FAILURE_RETRY(write(sock.Get(), &send[done], send.size() - done)); - if (-1 == temp) { - int err = errno; - LogError("Error in write: " << strerror(err)); - return SECURITY_MANAGER_API_ERROR_SOCKET; - } - done += temp; - } - - do { - if (0 >= waitForSocket(sock.Get(), POLLIN, POLL_TIMEOUT)) { - LogError("Error in poll(POLLIN)"); - return SECURITY_MANAGER_API_ERROR_SOCKET; - } - ssize_t temp = TEMP_FAILURE_RETRY(read(sock.Get(), buffer, 2048)); - if (-1 == temp) { - int err = errno; - LogError("Error in read: " << strerror(err)); - return SECURITY_MANAGER_API_ERROR_SOCKET; - } - - if (0 == temp) { - LogError("Read return 0/Connection closed by server(?)"); - return SECURITY_MANAGER_API_ERROR_SOCKET; - } - - RawBuffer raw(buffer, buffer+temp); - recv.Push(raw); - } while(!recv.Ready()); - return SECURITY_MANAGER_API_SUCCESS; -} - -int sendToServerAncData(char const * const interface, const RawBuffer &send, struct msghdr &hdr) { - int ret; - SockRAII sock; - ssize_t done = 0; - - if (SECURITY_MANAGER_API_SUCCESS != (ret = sock.Connect(interface))) { - LogError("Error in SockRAII"); - return ret; - } - - while ((send.size() - done) > 0) { - if (0 >= waitForSocket(sock.Get(), POLLOUT, POLL_TIMEOUT)) { - LogError("Error in poll(POLLOUT)"); - return SECURITY_MANAGER_API_ERROR_SOCKET; - } - ssize_t temp = TEMP_FAILURE_RETRY(write(sock.Get(), &send[done], send.size() - done)); - if (-1 == temp) { - int err = errno; - LogError("Error in write: " << strerror(err)); - return SECURITY_MANAGER_API_ERROR_SOCKET; - } - done += temp; - } - - if (0 >= waitForSocket(sock.Get(), POLLIN, POLL_TIMEOUT)) { - LogError("Error in poll(POLLIN)"); - return SECURITY_MANAGER_API_ERROR_SOCKET; - } - - ssize_t temp = TEMP_FAILURE_RETRY(recvmsg(sock.Get(), &hdr, MSG_CMSG_CLOEXEC)); - - if (temp < 0) { - int err = errno; - LogError("Error in recvmsg(): " << strerror(err) << " errno: " << err); - return SECURITY_MANAGER_API_ERROR_SOCKET; - } - - if (0 == temp) { - LogError("Read return 0/Connection closed by server(?)"); - return SECURITY_MANAGER_API_ERROR_SOCKET; - } - - return SECURITY_MANAGER_API_SUCCESS; -} - int try_catch(const std::function& func) { try { diff --git a/src/client/client-offline.cpp b/src/client/client-offline.cpp index e442c2f..d60911d 100644 --- a/src/client/client-offline.cpp +++ b/src/client/client-offline.cpp @@ -22,12 +22,13 @@ * @brief Helper class for client "off-line" mode detection */ +#include #include #include #include +#include #include #include -#include "client-offline.h" namespace SecurityManager { diff --git a/src/client/client-security-manager.cpp b/src/client/client-security-manager.cpp index 74a6b30..4d6fecb 100644 --- a/src/client/client-security-manager.cpp +++ b/src/client/client-security-manager.cpp @@ -44,6 +44,8 @@ #include #include #include +#include + #include #include diff --git a/src/client/include/client-common.h b/src/client/include/client-common.h index c7d18a4..b82f6a5 100644 --- a/src/client/include/client-common.h +++ b/src/client/include/client-common.h @@ -26,34 +26,13 @@ #ifndef _SECURITY_MANAGER_CLIENT_ #define _SECURITY_MANAGER_CLIENT_ -#include #include -#include - #define SECURITY_MANAGER_API __attribute__((visibility("default"))) #define SECURITY_MANAGER_UNUSED __attribute__((unused)) -extern "C" { - struct msghdr; -} - namespace SecurityManager { -typedef std::vector RawBuffer; - -int sendToServer(char const * const interface, const RawBuffer &send, MessageBuffer &recv); - -/* - * sendToServerAncData is special case when we want to receive file descriptor - * passed by Security Manager on behalf of calling process. We can't get it with - * MessageBuffer. - * - * This function should be called _ONLY_ in this particular case. - * - */ -int sendToManagerAncData(char const * const interface, const RawBuffer &send, struct msghdr &hdr); - /* * Decorator function that performs frequently repeated exception handling in * SS client API functions. Accepts lambda expression as an argument. diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 2da9c3e..6571e64 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -41,6 +41,7 @@ SET(COMMON_SOURCES ${DPL_PATH}/core/src/string.cpp ${DPL_PATH}/db/src/naive_synchronization_object.cpp ${DPL_PATH}/db/src/sql_connection.cpp + ${COMMON_PATH}/connection.cpp ${COMMON_PATH}/cynara.cpp ${COMMON_PATH}/file-lock.cpp ${COMMON_PATH}/protocols.cpp diff --git a/src/common/connection.cpp b/src/common/connection.cpp new file mode 100644 index 0000000..e4dc9ee --- /dev/null +++ b/src/common/connection.cpp @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Rafal Krypa + * + * 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 + */ +/* + * @file connection.cpp + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @version 1.0 + * @brief This file is implementation of common connection functions. + */ + +#include "connection.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +namespace { + +const int POLL_TIMEOUT = -1; + +int waitForSocket(int sock, int event, int timeout) { + int retval; + pollfd desc[1]; + desc[0].fd = sock; + desc[0].events = event; + + while((-1 == (retval = poll(desc, 1, timeout))) && (errno == EINTR)) { + timeout >>= 1; + errno = 0; + } + + if (0 == retval) { + LogDebug("Poll timeout"); + } else if (-1 == retval) { + int err = errno; + LogError("Error in poll: " << strerror(err)); + } + return retval; +} + +class SockRAII { +public: + SockRAII() + : m_sock(-1) + {} + + virtual ~SockRAII() { + if (m_sock > -1) + close(m_sock); + } + + int Connect(char const * const interface) { + sockaddr_un clientAddr; + int flags; + + if (m_sock != -1) // guard + close(m_sock); + + m_sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (m_sock < 0) { + int err = errno; + LogError("Error creating socket: " << strerror(err)); + return SECURITY_MANAGER_API_ERROR_SOCKET; + } + + if ((flags = fcntl(m_sock, F_GETFL, 0)) < 0 || + fcntl(m_sock, F_SETFL, flags | O_NONBLOCK) < 0) + { + int err = errno; + LogError("Error in fcntl: " << strerror(err)); + return SECURITY_MANAGER_API_ERROR_SOCKET; + } + + memset(&clientAddr, 0, sizeof(clientAddr)); + + clientAddr.sun_family = AF_UNIX; + + if (strlen(interface) >= sizeof(clientAddr.sun_path)) { + LogError("Error: interface name " << interface << "is too long. Max len is:" << sizeof(clientAddr.sun_path)); + return SECURITY_MANAGER_API_ERROR_NO_SUCH_SERVICE; + } + + strcpy(clientAddr.sun_path, interface); + + LogDebug("ClientAddr.sun_path = " << interface); + + int retval = TEMP_FAILURE_RETRY(connect(m_sock, (struct sockaddr*)&clientAddr, SUN_LEN(&clientAddr))); + if ((retval == -1) && (errno == EINPROGRESS)) { + if (0 >= waitForSocket(m_sock, POLLIN, POLL_TIMEOUT)) { + LogError("Error in waitForSocket."); + return SECURITY_MANAGER_API_ERROR_SOCKET; + } + int error = 0; + socklen_t len = sizeof(error); + retval = getsockopt(m_sock, SOL_SOCKET, SO_ERROR, &error, &len); + + if (-1 == retval) { + int err = errno; + LogError("Error in getsockopt: " << strerror(err)); + return SECURITY_MANAGER_API_ERROR_SOCKET; + } + + if (error == EACCES) { + LogError("Access denied"); + return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED; + } + + if (error != 0) { + LogError("Error in connect: " << strerror(error)); + return SECURITY_MANAGER_API_ERROR_SOCKET; + } + + return SECURITY_MANAGER_API_SUCCESS; + } + + if (-1 == retval) { + int err = errno; + LogError("Error connecting socket: " << strerror(err)); + if (err == EACCES) + return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED; + if (err == ENOTSOCK) + return SECURITY_MANAGER_API_ERROR_NO_SUCH_SERVICE; + return SECURITY_MANAGER_API_ERROR_SOCKET; + } + + return SECURITY_MANAGER_API_SUCCESS; + } + + int Get() { + return m_sock; + } + +private: + int m_sock; +}; + +} // namespace anonymous + +namespace SecurityManager { + +int sendToServer(char const * const interface, const RawBuffer &send, MessageBuffer &recv) { + int ret; + SockRAII sock; + ssize_t done = 0; + char buffer[2048]; + + if (SECURITY_MANAGER_API_SUCCESS != (ret = sock.Connect(interface))) { + LogError("Error in SockRAII"); + return ret; + } + + while ((send.size() - done) > 0) { + if (0 >= waitForSocket(sock.Get(), POLLOUT, POLL_TIMEOUT)) { + LogError("Error in poll(POLLOUT)"); + return SECURITY_MANAGER_API_ERROR_SOCKET; + } + ssize_t temp = TEMP_FAILURE_RETRY(write(sock.Get(), &send[done], send.size() - done)); + if (-1 == temp) { + int err = errno; + LogError("Error in write: " << strerror(err)); + return SECURITY_MANAGER_API_ERROR_SOCKET; + } + done += temp; + } + + do { + if (0 >= waitForSocket(sock.Get(), POLLIN, POLL_TIMEOUT)) { + LogError("Error in poll(POLLIN)"); + return SECURITY_MANAGER_API_ERROR_SOCKET; + } + ssize_t temp = TEMP_FAILURE_RETRY(read(sock.Get(), buffer, 2048)); + if (-1 == temp) { + int err = errno; + LogError("Error in read: " << strerror(err)); + return SECURITY_MANAGER_API_ERROR_SOCKET; + } + + if (0 == temp) { + LogError("Read return 0/Connection closed by server(?)"); + return SECURITY_MANAGER_API_ERROR_SOCKET; + } + + RawBuffer raw(buffer, buffer+temp); + recv.Push(raw); + } while(!recv.Ready()); + return SECURITY_MANAGER_API_SUCCESS; +} + +int sendToServerAncData(char const * const interface, const RawBuffer &send, struct msghdr &hdr) { + int ret; + SockRAII sock; + ssize_t done = 0; + + if (SECURITY_MANAGER_API_SUCCESS != (ret = sock.Connect(interface))) { + LogError("Error in SockRAII"); + return ret; + } + + while ((send.size() - done) > 0) { + if (0 >= waitForSocket(sock.Get(), POLLOUT, POLL_TIMEOUT)) { + LogError("Error in poll(POLLOUT)"); + return SECURITY_MANAGER_API_ERROR_SOCKET; + } + ssize_t temp = TEMP_FAILURE_RETRY(write(sock.Get(), &send[done], send.size() - done)); + if (-1 == temp) { + int err = errno; + LogError("Error in write: " << strerror(err)); + return SECURITY_MANAGER_API_ERROR_SOCKET; + } + done += temp; + } + + if (0 >= waitForSocket(sock.Get(), POLLIN, POLL_TIMEOUT)) { + LogError("Error in poll(POLLIN)"); + return SECURITY_MANAGER_API_ERROR_SOCKET; + } + + ssize_t temp = TEMP_FAILURE_RETRY(recvmsg(sock.Get(), &hdr, MSG_CMSG_CLOEXEC)); + + if (temp < 0) { + int err = errno; + LogError("Error in recvmsg(): " << strerror(err) << " errno: " << err); + return SECURITY_MANAGER_API_ERROR_SOCKET; + } + + if (0 == temp) { + LogError("Read return 0/Connection closed by server(?)"); + return SECURITY_MANAGER_API_ERROR_SOCKET; + } + + return SECURITY_MANAGER_API_SUCCESS; +} + +} // namespace SecurityManager diff --git a/src/common/include/connection.h b/src/common/include/connection.h new file mode 100644 index 0000000..77967c4 --- /dev/null +++ b/src/common/include/connection.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Rafal Krypa + * + * 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 + */ +/* + * @file sock-raii.h + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @version 1.0 + * @brief This file constains declarations of connection-related functions + * used in security manager. + */ + +#ifndef _SECURITY_MANAGER_CONNECTION_ +#define _SECURITY_MANAGER_CONNECTION_ + +#include +#include + +#include + +extern "C" { + struct msghdr; +} + +namespace SecurityManager { + +typedef std::vector RawBuffer; + +int sendToServer(char const * const interface, const RawBuffer &send, MessageBuffer &recv); + +/* + * sendToServerAncData is special case when we want to receive file descriptor + * passed by Security Manager on behalf of calling process. We can't get it with + * MessageBuffer. + * + * This function should be called _ONLY_ in this particular case. + * + */ +int sendToManagerAncData(char const * const interface, const RawBuffer &send, struct msghdr &hdr); + +} // namespace SecurityManager + +#endif // _SECURITY_MANAGER_CONNECTION_ diff --git a/src/server/service/service.cpp b/src/server/service/service.cpp index 522356f..334ce19 100644 --- a/src/server/service/service.cpp +++ b/src/server/service/service.cpp @@ -29,6 +29,7 @@ #include #include +#include "connection.h" #include "protocols.h" #include "service.h" #include "service_impl.h" -- 2.7.4