Check whether client process label is allowed or not on whitelist 22/83322/3
authorjooseong lee <jooseong.lee@samsung.com>
Wed, 10 Aug 2016 05:56:50 +0000 (14:56 +0900)
committerjooseong lee <jooseong.lee@samsung.com>
Wed, 24 Aug 2016 09:13:33 +0000 (18:13 +0900)
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>
CMakeLists.txt
conf/CMakeLists.txt [new file with mode: 0644]
conf/admin-client-whitelist [new file with mode: 0644]
conf/client-whitelist [new file with mode: 0644]
conf/client-whitelist_mobile [new file with mode: 0644]
packaging/auth-fw.spec
src/server/main/include/smack-check.h
src/server/main/smack-check.cpp
src/server/service/password.cpp
src/server/service/policy-file.cpp

index e0d0f4def79a7c12118d285a35333d46d2bb6882..e3afdcc5d32276609d644db14ed9411d3703e4d6 100644 (file)
@@ -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 (file)
index 0000000..c0aaf8b
--- /dev/null
@@ -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 (file)
index 0000000..5e88c28
--- /dev/null
@@ -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 (file)
index 0000000..8e5a96c
--- /dev/null
@@ -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 (file)
index 0000000..362ee23
--- /dev/null
@@ -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
index 99187acb166c276e78fe88d78b4257f2a54a5333..cefd5c92999da4951454256e838e2caf105535d1 100644 (file)
@@ -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
index b2c9812dd94f4c88dafdd6447ec3050772fdc50e..024c670ec6f5dbdae77e4f0837e16f0f6e192c5e 100644 (file)
 #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_
index 5c3b3b9a024af5ad7682b3bb71c599b846af41a1..66b26f5deabb2d2abb41cb94f693680f70d8c6ac 100644 (file)
  */
 #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
index f165c7f072768edbe34ae60a763eda3c0393c269..005b6bca1468e8f28f2d270b92b72bb745640971 100644 (file)
@@ -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:
index 5e7f15a3d8aada7342a567bb73ac369b8dd1bf7d..cc3bf8a8c43d84c2dcf7d8272902fe91afaabb48 100644 (file)
@@ -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);