diff options
author | jooseong lee <jooseong.lee@samsung.com> | 2016-08-10 14:56:50 +0900 |
---|---|---|
committer | jooseong lee <jooseong.lee@samsung.com> | 2016-08-24 18:13:33 +0900 |
commit | 0e3e87f1c1575ec776df45b31583bdbee86eb068 (patch) | |
tree | 579f685262df4bef47dfff6d67db7dd9657b09c1 | |
parent | de3c3d2d97c34fa27cb1778d2b81686317d026ef (diff) | |
download | auth-fw-0e3e87f1c1575ec776df45b31583bdbee86eb068.tar.gz auth-fw-0e3e87f1c1575ec776df45b31583bdbee86eb068.tar.bz2 auth-fw-0e3e87f1c1575ec776df45b31583bdbee86eb068.zip |
Check whether client process label is allowed or not on whitelist
Only allowed client should call password APIs. Auth-fw can manage it
based on whitelist. There are two whitelist files for general client
and admin client.
- client-whitelist
: subject labels allowed to use password checking/setting
ex. lockscreen, setting application
- admin-client-whitelist
: subject labels allowed to use password reset and password policy setting
ex. device policy manager
Change-Id: If4eebde05f690c8fd8a9e8c5adce08f0c7af5e47
Signed-off-by: jooseong lee <jooseong.lee@samsung.com>
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | conf/CMakeLists.txt | 24 | ||||
-rw-r--r-- | conf/admin-client-whitelist | 4 | ||||
-rw-r--r-- | conf/client-whitelist | 5 | ||||
-rw-r--r-- | conf/client-whitelist_mobile | 9 | ||||
-rw-r--r-- | packaging/auth-fw.spec | 6 | ||||
-rw-r--r-- | src/server/main/include/smack-check.h | 11 | ||||
-rw-r--r-- | src/server/main/smack-check.cpp | 59 | ||||
-rw-r--r-- | src/server/service/password.cpp | 21 | ||||
-rw-r--r-- | src/server/service/policy-file.cpp | 2 |
10 files changed, 133 insertions, 9 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e0d0f4d..e3afdcc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,3 +68,4 @@ ENDIF (CMAKE_BUILD_TYPE MATCHES "DEBUG") ADD_SUBDIRECTORY(src) ADD_SUBDIRECTORY(pkgconfig) ADD_SUBDIRECTORY(systemd) +ADD_SUBDIRECTORY(conf) diff --git a/conf/CMakeLists.txt b/conf/CMakeLists.txt new file mode 100644 index 0000000..c0aaf8b --- /dev/null +++ b/conf/CMakeLists.txt @@ -0,0 +1,24 @@ +# Copyright (c) 2015 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. +# +# @file CMakeLists.txt +# @author Jooseong Lee <jooseong.lee@samsung.com> +# +IF("${PROFILE}" STREQUAL "mobile") + INSTALL(FILES client-whitelist_mobile DESTINATION ${SYS_CONFIG_DIR}/${SERVICE_NAME} RENAME client-whitelist) +ELSE("${PROFILE}" STREQUAL "mobile") + INSTALL(FILES client-whitelist DESTINATION ${SYS_CONFIG_DIR}/${SERVICE_NAME}) +ENDIF() + +INSTALL(FILES admin-client-whitelist DESTINATION ${SYS_CONFIG_DIR}/${SERVICE_NAME}) diff --git a/conf/admin-client-whitelist b/conf/admin-client-whitelist new file mode 100644 index 0000000..5e88c28 --- /dev/null +++ b/conf/admin-client-whitelist @@ -0,0 +1,4 @@ +# subject labels allowed to use password reset and password policy setting +# put each allowed label in new line +System +System::Privileged diff --git a/conf/client-whitelist b/conf/client-whitelist new file mode 100644 index 0000000..8e5a96c --- /dev/null +++ b/conf/client-whitelist @@ -0,0 +1,5 @@ +# subject labels allowed to use password checking/setting +# put each allowed label in new line +System +System::Privileged +User diff --git a/conf/client-whitelist_mobile b/conf/client-whitelist_mobile new file mode 100644 index 0000000..362ee23 --- /dev/null +++ b/conf/client-whitelist_mobile @@ -0,0 +1,9 @@ +# subject labels allowed to use password checking/setting +# put each allowed label in new line +System +System::Privileged +User +User::App::org.tizen.keyguard +User::App::org.tizen.lockscreen +User::App::setting-password-efl +User::App::setting-locktype-efl diff --git a/packaging/auth-fw.spec b/packaging/auth-fw.spec index 99187ac..cefd5c9 100644 --- a/packaging/auth-fw.spec +++ b/packaging/auth-fw.spec @@ -84,6 +84,7 @@ export LDFLAGS+="-Wl,--rpath=%{_libdir}" -DSERVICE_NAME=%{name} \ -DBIN_DIR:PATH=%{bin_dir} \ -DSBIN_DIR:PATH=%{sbin_dir} \ + -DSYS_CONFIG_DIR:PATH=%{_sysconfdir} \ -DRUN_DIR:PATH=%{run_dir} \ -DRW_DATA_DIR:PATH=%{rw_data_dir} \ -DSYSTEMD_UNIT_DIR:PATH=%{_unitdir} \ @@ -91,7 +92,8 @@ export LDFLAGS+="-Wl,--rpath=%{_libdir}" -DSOCK_PASSWD_CHECK=%{sock_passwd_check} \ -DSOCK_PASSWD_SET=%{sock_passwd_set} \ -DSOCK_PASSWD_RESET=%{sock_passwd_reset} \ - -DSOCK_PASSWD_POLICY=%{sock_passwd_policy} + -DSOCK_PASSWD_POLICY=%{sock_passwd_policy} \ + -DPROFILE=%{profile} make %{?jobs:-j%jobs} @@ -156,6 +158,8 @@ fi %{_unitdir}/sockets.target.wants/%{sock_passwd_set} %{_unitdir}/sockets.target.wants/%{sock_passwd_reset} %{_unitdir}/sockets.target.wants/%{sock_passwd_policy} +%{_sysconfdir}/%{name}/client-whitelist +%{_sysconfdir}/%{name}/admin-client-whitelist %dir %attr(770, %{user_name}, %{group_name}) %{rw_data_dir} %files -n lib%{name}-client diff --git a/src/server/main/include/smack-check.h b/src/server/main/include/smack-check.h index b2c9812..024c670 100644 --- a/src/server/main/include/smack-check.h +++ b/src/server/main/include/smack-check.h @@ -21,8 +21,13 @@ #ifndef _SMACK_CHECK_H_ #define _SMACK_CHECK_H_ +#include <string> + namespace AuthPasswd { +extern const std::string CLIENT_WHITELIST; +extern const std::string ADMIN_CLIENT_WHITELIST; + /* * A very simple runtime check for SMACK on the platform * Returns 1 if SMACK is present, 0 otherwise. If SMACK_ENABLED is not defined @@ -30,6 +35,12 @@ namespace AuthPasswd { */ int smack_check(void); +/* + * Check whether client is allowed or not on whitelist. + * Returns true if client label is present, fail otherwise. + */ +bool checkClientOnWhitelist(int sockfd, std::string whitelistPath); + } // namespace AuthPasswd #endif // _SMACK_CHECK_H_ diff --git a/src/server/main/smack-check.cpp b/src/server/main/smack-check.cpp index 5c3b3b9..66b26f5 100644 --- a/src/server/main/smack-check.cpp +++ b/src/server/main/smack-check.cpp @@ -21,13 +21,20 @@ */ #include "smack-check.h" -#include <stdlib.h> +#include <fstream> #include <sys/smack.h> +#include <sys/socket.h> +#include <sys/un.h> #include <dpl/log/log.h> +#include <error-description.h> namespace AuthPasswd { +const char COMMENT = '#'; +const std::string CLIENT_WHITELIST = "/etc/auth-fw/client-whitelist"; +const std::string ADMIN_CLIENT_WHITELIST = "/etc/auth-fw/admin-client-whitelist"; + int smack_runtime_check(void) { static int smack_present = -1; @@ -54,4 +61,54 @@ int smack_check(void) #endif } +bool checkClientOnWhitelist(int sockfd, std::string whitelistPath) +{ + struct ucred cr; + socklen_t len = sizeof(struct ucred); + + // get client smack label from socket + if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cr, &len)) { + int err = errno; + LogError("getsockopt() failed: " << errnoToString(err)); + return false; + } + + std::string clientSmackLabel; + std::string path("/proc/" + std::to_string(cr.pid) + "/attr/current"); + std::ifstream file(path.c_str()); + if (!file.is_open()) { + LogError("failed to open " << path); + return false; + } + + std::getline(file, clientSmackLabel); + file.close(); + if (clientSmackLabel.empty()) + return false; + + // compare with whitelist labels + std::string line; + std::ifstream whitelistFile(whitelistPath.c_str()); + if (!whitelistFile.is_open()) { + LogError("failed to open " << whitelistPath); + return false; + } + + while (std::getline(whitelistFile, line)) { + if (line.empty()) + continue; + if (line.at(0) == COMMENT) + continue; + if (line.compare(clientSmackLabel) == 0) { + whitelistFile.close(); + LogDebug("Client " << clientSmackLabel << " is on whitelist"); + return true; + } + } + whitelistFile.close(); + LogError("Client " << clientSmackLabel << " is not on whitelist"); + + return false; +} + } // namespace AuthPasswd diff --git a/src/server/service/password.cpp b/src/server/service/password.cpp index f165c7f..005b6bc 100644 --- a/src/server/service/password.cpp +++ b/src/server/service/password.cpp @@ -30,6 +30,7 @@ #include <dpl/log/log.h> #include <dpl/serialization.h> +#include <smack-check.h> #include <user-check.h> #include <password.h> @@ -313,27 +314,35 @@ bool PasswordService::processOne(const ConnectionID &conn, MessageBuffer &buffer try { //try..catch for internal service errors, assigns error code for returning. switch (interfaceID) { case SOCKET_ID_CHECK: - if (socket_get_user(conn.sock, cur_user)) + if (!checkClientOnWhitelist(conn.sock, CLIENT_WHITELIST)) + retCode = AUTH_PASSWD_API_ERROR_ACCESS_DENIED; + else if (socket_get_user(conn.sock, cur_user)) retCode = AUTH_PASSWD_API_ERROR_NO_USER; else retCode = processCheckFunctions(hdr, buffer, cur_user, cur_att, max_att, exp_time); - break; case SOCKET_ID_SET: - if (socket_get_user(conn.sock, cur_user)) + if (!checkClientOnWhitelist(conn.sock, CLIENT_WHITELIST)) + retCode = AUTH_PASSWD_API_ERROR_ACCESS_DENIED; + else if (socket_get_user(conn.sock, cur_user)) retCode = AUTH_PASSWD_API_ERROR_NO_USER; else retCode = processSetFunctions(hdr, buffer, cur_user, isPwdReused); - break; case SOCKET_ID_RESET: - retCode = processResetFunctions(hdr, buffer); + if (!checkClientOnWhitelist(conn.sock, ADMIN_CLIENT_WHITELIST)) + retCode = AUTH_PASSWD_API_ERROR_ACCESS_DENIED; + else + retCode = processResetFunctions(hdr, buffer); break; case SOCKET_ID_POLICY: - retCode = processPolicyFunctions(hdr, buffer); + if (!checkClientOnWhitelist(conn.sock, ADMIN_CLIENT_WHITELIST)) + retCode = AUTH_PASSWD_API_ERROR_ACCESS_DENIED; + else + retCode = processPolicyFunctions(hdr, buffer); break; default: diff --git a/src/server/service/policy-file.cpp b/src/server/service/policy-file.cpp index 5e7f15a..cc3bf8a 100644 --- a/src/server/service/policy-file.cpp +++ b/src/server/service/policy-file.cpp @@ -122,7 +122,7 @@ std::string PolicyFile::createDir(const std::string &dir, unsigned int user) con void PolicyFile::writeMemoryToFile() const { PasswordFileBuffer policyBuffer; - LogSecureDebug("User: " << m_user << "Policy: " << m_policy.info()); + LogSecureDebug("User: " << m_user << " Policy: " << m_policy.info()); // serialize policy attributes Serialization::Serialize(policyBuffer, CURRENT_FILE_VERSION); Serialization::Serialize(policyBuffer, m_enable); |