STRING(REGEX MATCH "([^.]*)" API_VERSION "${VERSION}")
ADD_DEFINITIONS("-DAPI_VERSION=\"$(API_VERSION)\"")
-ADD_DEFINITIONS("-DSMACK_ENABLED")
ADD_DEFINITIONS("-DSQLITE_HAS_CODEC")
ADD_DEFINITIONS("-DDUMP_LEGACY_DB_LIBNAME=\"${DUMP_LEGACY_DB_LIBNAME}\"")
ADD_DEFINITIONS("-DLIB_INSTALL_DIR=\"${LIB_INSTALL_DIR}\"")
dlog
glib-2.0
openssl3
- libsmack
libsystemd
capi-base-common
capi-system-info
)
ADD_SUBDIRECTORY(ckm_db_tool)
ADD_SUBDIRECTORY(ckm_initial_values)
-ADD_SUBDIRECTORY(encryption_scheme)
+IF (SMACK_ENABLED)
+ ADD_SUBDIRECTORY(encryption_scheme)
+ENDIF (SMACK_ENABLED)
ADD_SUBDIRECTORY(db_perf)
ADD_SUBDIRECTORY(update_perf)
-ADD_SUBDIRECTORY(encryption_perf)
\ No newline at end of file
+ADD_SUBDIRECTORY(encryption_perf)
+
+CONFIGURE_FILE(
+ ${PROJECT_SOURCE_DIR}/packaging/key-manager-misc.manifest.in
+ ${PROJECT_SOURCE_DIR}/key-manager-misc.manifest @ONLY
+)
${KEY_MANAGER_PATH}/initial-values/xml-utils.cpp
${KEY_MANAGER_PATH}/main/cynara.cpp
${KEY_MANAGER_PATH}/main/generic-socket-manager.cpp
- ${KEY_MANAGER_PATH}/main/smack-check.cpp
${KEY_MANAGER_PATH}/main/socket-2-id.cpp
${KEY_MANAGER_PATH}/main/socket-manager.cpp
${KEY_MANAGER_PATH}/main/thread-service.cpp
ADD_DEFINITIONS("-DBOOST_TEST_DYN_LINK")
ADD_DEFINITIONS("-DMISC_DIR=\"${MISC_DIR}\"")
+PKG_CHECK_MODULES(MISC_DEP
+ REQUIRED
+ libsmack
+ )
+
SET(MANAGER_PATH ${PROJECT_SOURCE_DIR}/src/manager)
-INCLUDE_DIRECTORIES(SYSTEM ${KEY_MANAGER_DEP_INCLUDE_DIRS})
+INCLUDE_DIRECTORIES(SYSTEM ${KEY_MANAGER_DEP_INCLUDE_DIRS} ${MISC_DEPS_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(
${MANAGER_PATH}/dpl/db/include
${TARGET_KEY_MANAGER_CLIENT}
${TARGET_KEY_MANAGER_CONTROL_CLIENT}
${KEY_MANAGER_DEP_LIBRARIES}
+ ${MISC_DEP_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
boost_unit_test_framework
-ldl
key-32bit
DESTINATION ${MISC_DIR}
)
-
-CONFIGURE_FILE(
- ${PROJECT_SOURCE_DIR}/packaging/key-manager-misc.manifest.in
- ${PROJECT_SOURCE_DIR}/key-manager-misc.manifest @ONLY
-)
BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(openssl3)
BuildRequires: libattr-devel
-BuildRequires: pkgconfig(libsmack)
BuildRequires: pkgconfig(libsystemd)
BuildRequires: pkgconfig(libxml-2.0)
BuildRequires: pkgconfig(capi-system-info)
%endif
BuildRequires: pkgconfig(capi-system-resource)
BuildRequires: liboqs
+%if "%{?dev_wos}" != "1"
+Requires: smack
+%endif
%{?systemd_requires}
License: Apache-2.0 and BSL-1.0
Requires: boost-test
Requires: key-manager = %{version}-%{release}
+%if "%{?dev_wos}" != "1"
+BuildRequires: pkgconfig(libsmack)
+%endif
+
%description -n key-manager-misc
Miscellaneous tools and tests for key-manager.
-DCOVERAGE_DIR=%{coverage_dir} \
%if %{coverage_only}
-DCOVERAGE_ONLY=ON \
+%endif
+%if "%{?dev_wos}" != "1"
+ -DSMACK_ENABLED=ON \
%endif
-DDUMP_LEGACY_DB_LIBNAME=%{dump_legacy_db_libname}
# update
# In ckm version <= 0.1.18 all files were owned by root.
+%if "%{?dev_wos}" != "1"
find %{rw_data_dir} -exec chsmack -a %{smack_domain_name} {} \;
+%endif
chown %{user_name}:%{group_name} -R %{rw_data_dir}
systemctl restart central-key-manager.service
fi
%manifest key-manager-misc.manifest
%license LICENSE
%license LICENSE.BSL-1.0
-%{bin_dir}/ckm-scheme-test
+%if "%{?dev_wos}" != "1"
+ %{bin_dir}/ckm-scheme-test
+ %{bin_dir}/ckm_generate_db
+ %misc_dir
+%endif
%{bin_dir}/ckm_so_loader
%{bin_dir}/ckm_db_tool
%{bin_dir}/ckm_db_merge
-%{bin_dir}/ckm_generate_db
%{bin_dir}/ckm_db_perf
%{bin_dir}/ckm_enc_perf
%{bin_dir}/ckm_update_perf
-%misc_dir
%endif
${KEY_MANAGER_PATH}/main/cynara.cpp
${KEY_MANAGER_PATH}/main/generic-socket-manager.cpp
${KEY_MANAGER_PATH}/main/key-manager-main.cpp
- ${KEY_MANAGER_PATH}/main/smack-check.cpp
${KEY_MANAGER_PATH}/main/socket-2-id.cpp
${KEY_MANAGER_PATH}/main/socket-manager.cpp
${KEY_MANAGER_PATH}/main/thread-service.cpp
REQUIRED
dlog
openssl3
- libsmack
libsystemd
)
+++ /dev/null
-/*
- * Copyright (c) 2014 - 2018 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
- */
-
-#include <smack-check.h>
-
-#include <stdlib.h>
-#include <sys/smack.h>
-
-#include <dpl/log/log.h>
-
-namespace CKM {
-
-int smack_runtime_check(void)
-{
- static int smack_present = -1;
-
- if (-1 == smack_present) {
- if (NULL == smack_smackfs_path()) {
- LogDebug("no smack found on device");
- smack_present = 0;
- } else {
- LogDebug("found smack on device");
- smack_present = 1;
- }
- }
-
- return smack_present;
-}
-
-int smack_check(void)
-{
-#ifndef SMACK_ENABLED
- return 0;
-#else
- return smack_runtime_check();
-#endif
-}
-
-} // namespace CKM
+++ /dev/null
-/*
- * ckm-manager
- *
- * Copyright (c) 2000-2019 Samsung Electronics Co., Ltd. All rights reserved
- *
- * Contact: Dongsun Lee <ds73.lee@samsung.com>
- *
- * 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
- */
-
-#ifndef _SMACK_CHECK_H_
-#define _SMACK_CHECK_H_
-
-namespace CKM {
-
-/*
- * A very simple runtime check for SMACK on the platform
- * Returns 1 if SMACK is present, 0 otherwise
- */
-
-int smack_runtime_check(void);
-
-/*
- * A very simple runtime check for SMACK on the platform
- * Returns 1 if SMACK is present, 0 otherwise. If SMACK_ENABLED is not defined
- * It returns 0.
- */
-int smack_check(void);
-
-} // namespace CKM
-
-#endif // _SMACK_CHECK_H_
#include "protocols.h"
#include "security-manager.h"
-#include <sys/smack.h>
#include <sys/types.h>
+#include <sys/socket.h>
namespace CKM {
-namespace {
+namespace Socket2Id {
-int getPkgIdFromSocket(int sock, std::string &pkgId)
-{
- char *pkg = nullptr;
-
- int ret = security_manager_identify_app_from_socket(sock, &pkg, nullptr);
-
- if (ret == SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT) {
- LogInfo("Owner of socket is not connected with pkgid. "
- "This case must be special-labled client. e.g. User, System");
- return 1;
- }
-
- if (ret != SECURITY_MANAGER_SUCCESS) {
- LogError("security_manager_identify_app_from_socket failed with error: "
- << ret);
- return -1;
- }
-
- pkgId = pkg;
- free(pkg);
- LogDebug("Socket: " << sock << " Was translated to owner id: " << pkgId);
- return 0;
-}
-
-int assignToString(std::vector<char> &vec, socklen_t len, std::string &res)
-{
- if (vec.size() <= len)
- return -1;
-
- vec[len] =
- 0; // old implementation getsockopt returns cstring without 0
-
- if (vec[len - 1] == 0)
- --len; // new implementation of getsockopt returns cstring size+1
-
- res.assign(vec.data(), len);
- return 0;
-}
-
-} // namespace anonymous
-
-int Socket2Id::getPeerCred(int sock, ucred &peerCred)
+bool translate(int sock, const std::string& cynaraClient, CKM::Credentials &creds)
{
+ ucred peerCred;
socklen_t length = sizeof(ucred);
-
if (0 > getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peerCred, &length)) {
LogError("getsockopt failed");
- return -1;
- }
- return 0;
-}
-
-int Socket2IdSmack::getCredentialsFromSocket(int sock, std::string &res)
-{
- std::vector<char> result(SMACK_LABEL_LEN + 1);
- socklen_t length = SMACK_LABEL_LEN;
-
- if (0 == getsockopt(sock, SOL_SOCKET, SO_PEERSEC, result.data(), &length))
- return assignToString(result, length, res);
-
- if (errno != ERANGE) {
- LogError("getsockopt failed with errno: " << errno);
- return -1;
- }
-
- result.resize(length + 1);
-
- if (0 > getsockopt(sock, SOL_SOCKET, SO_PEERSEC, result.data(), &length)) {
- LogError("getsockopt failed with errno: " << errno);
- return -1;
- }
-
- return assignToString(result, length, res);
-}
-
-void Socket2IdSmack::mapToDomainClient(std::string &pkgId)
-{
- static const std::string subdomainSep = "::";
- static const auto systemClientLen = strlen(CLIENT_ID_SYSTEM);
-
- if (pkgId.length() > systemClientLen + subdomainSep.length() &&
- pkgId.compare(0, systemClientLen, CLIENT_ID_SYSTEM) == 0 &&
- pkgId.compare(systemClientLen, subdomainSep.length(), subdomainSep) == 0) {
- pkgId = CLIENT_ID_SYSTEM;
+ return false;
}
-}
-
-int Socket2IdSmack::translate(int sock, CKM::Credentials &creds)
-{
- ucred peerCred;
- if (0 > Socket2Id::getPeerCred(sock, peerCred))
- return -1;
-
- creds.clientUid = peerCred.uid;
-
- std::string smack;
-
- if (0 > getCredentialsFromSocket(sock, smack))
- return -1;
-
- auto it = m_smack2pkgId.find(smack);
-
- if (it != m_smack2pkgId.end()) {
- creds.client = it->second;
- return 0;
- }
-
- std::string pkgId;
- int retCode = getPkgIdFromSocket(sock, pkgId);
-
- if (retCode < 0)
- return -1;
-
- if (retCode == 1) {
- LogInfo("Special smack label case. label: " << smack);
- pkgId = "/" + smack;
- }
-
- mapToDomainClient(pkgId);
-
- creds.client = pkgId;
- m_smack2pkgId.emplace(std::move(smack), std::move(pkgId));
- return 0;
-}
-
-int Socket2IdDac::translate(int sock, CKM::Credentials &creds)
-{
- ucred peerCred;
- if (0 > Socket2Id::getPeerCred(sock, peerCred))
- return -1;
+ /*
+ * Get user on behalf of which the app is running.
+ *
+ * For smack it will simply return the process uid.
+ *
+ * For uid sandboxing it will return:
+ * - the user which started the app using security_manager_prepare_app2()
+ * - SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT if it's a system service, or some other process not
+ * started with security_manager_prepare_app2()
+ */
int ret = security_manager_get_app_owner_uid(peerCred.pid, &creds.clientUid);
if (ret == SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT) {
if (AccessControl::isSystemService(peerCred.uid)) {
creds.client = CLIENT_ID_UNKNOWN;
}
creds.clientUid = peerCred.uid;
- return 0;
- } else if (ret != SECURITY_MANAGER_SUCCESS) {
- LogError("security_manager_get_app_owner_uid failed");
- return -1;
+ return true;
}
- int retCode = getPkgIdFromSocket(sock, creds.client);
- return retCode < 0 ? -1: 0;
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ LogError("security_manager_get_app_owner_uid failed with " << ret);
+ return false;
+ }
+
+ /*
+ * At this point this is either smack or a known application in uid-sandboxing.
+ *
+ * Try to get the app package id
+ *
+ * For smack it will return:
+ * - <PkgId> extracted from label User::Pkg::<PkgId>... for an existing app
+ * - <PkgId> extracted from label User::Pkg::<PkgId>... for a non-existing app (no check is
+ * performed)
+ * - SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT for system services (labels not matching
+ * "User::Pkg...")
+ *
+ * For uid sandboxing it will return:
+ * - <PkgId> retrieved from security-manager's db using process uid for an existing app
+ * - Other processes are handled above so SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT must not happen
+ */
+ char* pkgId = nullptr;
+ ret = security_manager_identify_app_from_socket(sock, &pkgId, nullptr);
+ if (ret == SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT) {
+ /*
+ * Use the client identifier from cynara and convert it to:
+ * - /System if it's "System::.*"
+ * - /<Label> in other cases (e.g. "User" -> "/User")
+ */
+ static const std::string systemClientPrefix = std::string(&CLIENT_ID_SYSTEM[1]) + "::";
+
+ if (cynaraClient.compare(0, systemClientPrefix.size(), systemClientPrefix) == 0) {
+ creds.client = CLIENT_ID_SYSTEM;
+ } else {
+ creds.client = std::string("/") + cynaraClient;
+ }
+ return true;
+ }
+
+ if (ret != SECURITY_MANAGER_SUCCESS || pkgId == nullptr) {
+ LogError("security_manager_identify_app_from_socket() failed with " << ret);
+ return false;
+ }
+
+ std::unique_ptr<std::remove_pointer_t<decltype(pkgId)>, decltype(&free)> pkgIdPtr(pkgId, free);
+ creds.client = pkgId;
+
+ return true;
}
+} // namespace Socket2Id
+
} // namespace CKM
#include "credentials.h"
-#include <map>
#include <string>
-#include <sys/socket.h>
-
namespace CKM {
-class Socket2Id {
-public:
- Socket2Id() {}
-
- virtual int translate(int sock, CKM::Credentials &creds) = 0;
-
- virtual ~Socket2Id() = default;
-
-protected:
- int getPeerCred(int sock, ucred &peerCred);
-};
-
-class Socket2IdSmack : public Socket2Id {
-public:
- int translate(int sock, CKM::Credentials &creds) override;
-
-private:
- int getCredentialsFromSocket(int sock, std::string &res);
- void mapToDomainClient(std::string &label);
-
- std::map<std::string, std::string> m_smack2pkgId;
-};
-
-class Socket2IdDac : public Socket2Id {
-public:
- int translate(int sock, CKM::Credentials &creds) override;
+namespace Socket2Id {
+bool translate(int sock, const std::string& cynaraClient, CKM::Credentials &creds);
};
} // namespace CKM
#include <sys/eventfd.h>
#include <sys/types.h>
#include <sys/socket.h>
-#include <sys/smack.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dpl/errno_string.h>
#include <dpl/log/log.h>
-#include <smack-check.h>
#include <socket-manager.h>
#include <socket-2-id.h>
const std::chrono::seconds SOCKET_TIMEOUT(1000);
#endif // OVERRIDE_SOCKET_TIMEOUT
-int getCredentialsFromSocket(int sock, CKM::Credentials &cred)
-{
- static auto sock2id =
- CKM::smack_check() ?
- std::unique_ptr<CKM::Socket2Id>(new CKM::Socket2IdSmack()) :
- std::unique_ptr<CKM::Socket2Id>(new CKM::Socket2IdDac());
- CKM::ClientId client;
-
- if (0 > sock2id->translate(sock, cred))
- return -1;
-
- return 0;
-}
-
std::chrono::time_point<std::chrono::steady_clock> monotonicNow() {
return std::chrono::steady_clock::now();
}
{
struct sockaddr_un clientAddr;
unsigned int clientLen = sizeof(clientAddr);
- int client = accept4(sock, (struct sockaddr *) &clientAddr, &clientLen,
+ int clientSocket = accept4(sock, (struct sockaddr *) &clientAddr, &clientLen,
SOCK_NONBLOCK);
- if (-1 == client) {
+ if (-1 == clientSocket) {
int err = errno;
LogDebug("Error in accept: " << GetErrnoString(err));
return;
}
- std::string smack;
+ std::string cynaraClient;
std::string user;
Credentials peerCred;
- if (0 > getCredentialsFromSocket(client, peerCred)
- || !Cynara::GetUserFromSocket(client, user)
- || !Cynara::GetClientFromSocket(client, smack)) {
+ if (!Cynara::GetClientFromSocket(clientSocket, cynaraClient) ||
+ !Socket2Id::translate(clientSocket, cynaraClient, peerCred) ||
+ !Cynara::GetUserFromSocket(clientSocket, user))
+ {
LogDebug("Error in getting credentials from socket.");
- close(client);
+ close(clientSocket);
return;
}
- auto &desc = CreateDefaultReadSocketDescription(client, true);
+ auto &desc = CreateDefaultReadSocketDescription(clientSocket, true);
desc.interfaceID = m_socketDescriptionVector[sock].interfaceID;
desc.service = m_socketDescriptionVector[sock].service;
desc.cynaraPrivilege = m_socketDescriptionVector[sock].cynaraPrivilege;
desc.cynaraUser = std::move(user);
- desc.cynaraClient = std::move(smack);
+ desc.cynaraClient = std::move(cynaraClient);
GenericSocketService::AcceptEvent event;
- event.connectionID.sock = client;
+ event.connectionID.sock = clientSocket;
event.connectionID.counter = desc.counter;
event.interfaceID = desc.interfaceID;
event.credentials = peerCred;
ThrowMsg(Exception::InitFailed, "Error in socket: " << GetErrnoString(err));
}
- if (smack_check()) {
- LogInfo("Set up smack label: " << desc.privilege);
-
- // if (0 != smack_fsetlabel(sockfd, desc.smackLabel.c_str(), SMACK_LABEL_IPIN)) {
- // LogError("Error in smack_fsetlabel");
- // ThrowMsg(Exception::InitFailed, "Error in smack_fsetlabel");
- // }
- } else {
- LogInfo("No smack on platform. Socket won't be securied with smack label!");
- }
-
int flags;
if (-1 == (flags = fcntl(sockfd, F_GETFL, 0)))
${MANAGER_PATH}/initial-values/parser.cpp
${MANAGER_PATH}/initial-values/xml-utils.cpp
${MANAGER_PATH}/main/cynara.cpp
- ${MANAGER_PATH}/main/smack-check.cpp
${MANAGER_PATH}/main/socket-2-id.cpp
${MANAGER_PATH}/main/socket-manager.cpp
${MANAGER_PATH}/service/crypto-logic.cpp