Store smack deny logs into files
authorMarek Smolinski <m.smolinski@samsung.com>
Thu, 31 Oct 2013 09:05:51 +0000 (10:05 +0100)
committerBartlomiej Grzelewski <b.grzelewski@samsung.com>
Thu, 6 Feb 2014 16:13:23 +0000 (17:13 +0100)
SS logs smack deny access into file in /var/log/audit/
Files are create sequential, if max file number in config is reach
it deleted oldest file and creates new one.

Configuration file security-server-audit.conf at
/etc/security/ containing number of files log and max size in bytes peer
file.

    [Issue#]        SSDWSSP-614
    [Bug/Feature]   SS creates log files on runtime and sequential
                    loging smack access
    [Cause]         N/A
    [Solution]      Add AuditSmackLog Class to manage log files
    [Verification]  Compile, run tests

Change-Id: I5d3e9c436bda6d545748da525cb3507488c47380

16 files changed:
packaging/security-server.manifest
packaging/security-server.spec
security-server-audit.conf [new file with mode: 0644]
src/server2/CMakeLists.txt
src/server2/dpl/log/include/dpl/log/abstract_log_provider.h
src/server2/dpl/log/include/dpl/log/audit-smack-log.h [new file with mode: 0644]
src/server2/dpl/log/include/dpl/log/dlog_log_provider.h
src/server2/dpl/log/include/dpl/log/log.h
src/server2/dpl/log/include/dpl/log/old_style_log_provider.h
src/server2/dpl/log/src/audit-smack-log.cpp [new file with mode: 0644]
src/server2/dpl/log/src/dlog_log_provider.cpp
src/server2/dpl/log/src/log.cpp
src/server2/dpl/log/src/old_style_log_provider.cpp
src/server2/main/server2-main.cpp
src/server2/service/cookie.cpp
src/server2/service/privilege-by-pid.cpp

index f5b8b87..c7d43d1 100644 (file)
                        <label name="security-server::api-get-gid" />
                        <label name="security-server::api-password-check" />
                        <label name="security-server::api-password-set" />
+                       <label name="security-server::audit-files" />
                </provide>
        </define>
        <request>
                <domain name="_" />
        </request>
+       <assign>
+               <filesystem path="/etc/security/security-server-audit.conf" label="security-server::audit-files" />
+       </assign>
 </manifest>
index 0b17806..a9b98b4 100644 (file)
@@ -73,6 +73,8 @@ rm -rf %{buildroot}
 mkdir -p %{buildroot}/usr/share/license
 cp LICENSE %{buildroot}/usr/share/license/%{name}
 cp LICENSE %{buildroot}/usr/share/license/libsecurity-server-client
+mkdir -p %{buildroot}/etc/security/
+cp security-server-audit.conf %{buildroot}/etc/security/
 %make_install
 
 mkdir -p %{buildroot}/usr/lib/systemd/system/multi-user.target.wants
@@ -146,6 +148,7 @@ fi
 %attr(-,root,root) /usr/lib/systemd/system/security-server-cookie-check.socket
 %attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/security-server-cookie-check-tmp.socket
 %attr(-,root,root) /usr/lib/systemd/system/security-server-cookie-check-tmp.socket
+%attr(-,root,root) /etc/security/security-server-audit.conf
 
 %{_datadir}/license/%{name}
 
diff --git a/security-server-audit.conf b/security-server-audit.conf
new file mode 100644 (file)
index 0000000..c977fda
--- /dev/null
@@ -0,0 +1 @@
+10 524288
index 154bf18..b24dd24 100644 (file)
@@ -12,6 +12,7 @@ SET(COMMON_SOURCES
     ${COMMON_PATH}/dpl/log/src/dlog_log_provider.cpp
     ${COMMON_PATH}/dpl/log/src/log.cpp
     ${COMMON_PATH}/dpl/log/src/old_style_log_provider.cpp
+    ${COMMON_PATH}/dpl/log/src/audit-smack-log.cpp
     ${COMMON_PATH}/dpl/core/src/assert.cpp
     ${COMMON_PATH}/dpl/core/src/binary_queue.cpp
     ${COMMON_PATH}/dpl/core/src/colors.cpp
index f94ec33..7679924 100644 (file)
@@ -67,6 +67,10 @@ class AbstractLogProvider
                        const char *fileName,
                        int line,
                        const char *function) = 0;
+    virtual void SmackAudit(const char *message,
+                       const char *fileName,
+                       int line,
+                       const char *function) = 0;
 
   protected:
     static const char *LocateSourceFileName(const char *filename);
diff --git a/src/server2/dpl/log/include/dpl/log/audit-smack-log.h b/src/server2/dpl/log/include/dpl/log/audit-smack-log.h
new file mode 100644 (file)
index 0000000..912ad53
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ *  Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@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
+ */
+/*
+ * @file        audit-smack-log.h
+ * @author      Marek Smolinski (m.smolinski@samsung.com)
+ * @version     1.0
+ * @brief       AuditSmackLog loging SMACK access deny sequentially into files
+ */
+
+#ifndef _AUDIT_SMACK_LOG_
+#define _AUDIT_SMACK_LOG_
+
+#include <dpl/log/abstract_log_provider.h>
+
+#include <map>
+#include <fstream>
+#include <mutex>
+#include <memory>
+#include <functional>
+
+namespace SecurityServer {
+namespace Log {
+
+class AuditSmackLog :
+    public AbstractLogProvider
+{
+public:
+    AuditSmackLog();
+    virtual ~AuditSmackLog();
+
+    bool Fail() const;
+
+    virtual void Debug(const char *message,
+                       const char *fileName,
+                       int line,
+                       const char *function);
+    virtual void Info(const char *message,
+                      const char *fileName,
+                      int line,
+                      const char *function);
+    virtual void Warning(const char *message,
+                         const char *fileName,
+                         int line,
+                         const char *function);
+    virtual void Error(const char *message,
+                       const char *fileName,
+                       int line,
+                       const char *function);
+    virtual void Pedantic(const char *message,
+                          const char *fileName,
+                          int line,
+                          const char *function);
+    virtual void SecureDebug(const char *message,
+                             const char *fileName,
+                             int line,
+                             const char *function);
+    virtual void SecureInfo(const char *message,
+                            const char *fileName,
+                            int line,
+                            const char *function);
+    virtual void SecureWarning(const char *message,
+                              const char *fileName,
+                              int line,
+                              const char *function);
+    virtual void SecureError(const char *message,
+                             const char *fileName,
+                             int line,
+                             const char *function);
+
+    virtual void SmackAudit(const char *message,
+                            const char *fileName,
+                            int line,
+                            const char *function);
+
+private:
+    void HandleWrite(const char *message,
+                     const char *fileName,
+                     int line,
+                     const char *function);
+
+    int CreateLogFile();
+    int RemoveOldestLogFile();
+    int ParseConfig();
+    int ProcessLogDir();
+    bool IsFileFull(std::ofstream &fs) const;
+
+    bool m_state;
+    unsigned int m_filesCount;
+    unsigned int m_fileMaxBytesSize;
+
+    std::map<time_t, std::string> m_fileNameMap;
+    std::ofstream m_outputStream;
+
+    std::mutex m_writeMtx;
+};
+
+}  // namespace Log
+}  // namespace SecurityServer
+#endif  // _AUDIT_SMACK_LOG_
index e569bf7..cd76c46 100644 (file)
@@ -79,11 +79,16 @@ class DLOGLogProvider :
                        const char *fileName,
                        int line,
                        const char *function);
+    virtual void SmackAudit(const char *message,
+                       const char *fileName,
+                       int line,
+                       const char *function);
 
     // Set global Tag according to DLOG
     void SetTag(const char *tag);
 };
-}
+
+} // namespace Log
 } // namespace SecurityServer
 
 #endif // SECURITYSERVER_DLOG_LOG_PROVIDER_H
index ca84108..9d8403a 100644 (file)
@@ -123,6 +123,14 @@ class LogSystem :
                const char *function);
 
     /**
+     * Log SS_SMACK into files
+     */
+     void SmackAudit(const char *message,
+                      const char *fileName,
+                      int line,
+                      const char *function);
+
+    /**
      * Set default's DLOG provider Tag
      */
     void SetTag(const char *tag);
@@ -191,6 +199,8 @@ do                                                                         \
 #define  LogError(message) DPL_MACRO_FOR_LOGGING(message, Error)
 #define  LogSecureError(message) DPL_MACRO_FOR_LOGGING(message, SecureError)
 
+#define  LogSmackAudit(message) DPL_MACRO_FOR_LOGGING(message, SmackAudit)
+
 #ifdef BUILD_TYPE_DEBUG
     #define LogDebug(message) DPL_MACRO_FOR_LOGGING(message, Debug)
     #define LogInfo(message) DPL_MACRO_FOR_LOGGING(message, Info)
index 42673a4..91eeb80 100644 (file)
@@ -93,6 +93,10 @@ class OldStyleLogProvider :
                        const char *fileName,
                        int line,
                        const char *function);
+    virtual void SmackAudit(const char *message,
+                      const char *fileName,
+                      int line,
+                      const char *function);
 };
 }
 } // namespace SecurityServer
diff --git a/src/server2/dpl/log/src/audit-smack-log.cpp b/src/server2/dpl/log/src/audit-smack-log.cpp
new file mode 100644 (file)
index 0000000..c442955
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ *  Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@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
+ */
+/*
+ * @file        audit-smack-log.cpp
+ * @author      Marek Smolinski (m.smolinski@samsung.com)
+ * @version     1.0
+ * @brief       AuditSmackLog loging SMACK access deny sequentially into files
+ */
+
+#include <iostream>
+#include <fstream>
+#include <map>
+#include <cstring>
+#include <mutex>
+
+#include <dirent.h>
+#include <time.h>
+#include <errno.h>
+#include <unistd.h>
+#include <cassert>
+
+#include <sys/smack.h>
+#include <sys/stat.h>
+
+#include <dpl/log/audit-smack-log.h>
+#include <dpl/log/log.h>
+
+#define UNUSED __attribute__((unused))
+
+namespace {
+
+const std::string AUDIT_CONFIG_LOG_PATH = "/etc/security/";
+const std::string AUDIT_CONFIG_FILENAME = "security-server-audit.conf";
+const std::string AUDIT_LOG_DIRECTORY = "/var/log/audit/";
+const std::string AUDIT_LOG_FILENAME_PREFIX = "audit-smack";
+const std::string AUDIT_LOG_SMACK_LABEL = "security-server::audit-files";
+
+} // namespace anonymous
+
+namespace SecurityServer {
+namespace Log {
+
+AuditSmackLog::AuditSmackLog()
+    : m_state(true), m_filesCount(0), m_fileMaxBytesSize(0)
+{
+    if (ParseConfig() != 0) {
+        goto error;
+    }
+
+    if (ProcessLogDir() != 0) {
+        goto error;
+    }
+
+    if (m_state) {
+
+        // reduce existing files count in log dir if config file was changed
+        while (m_fileNameMap.size() > m_filesCount) {
+            if (RemoveOldestLogFile() != 0) {
+                goto error;
+            }
+        }
+
+        if (m_fileNameMap.size() == 0) {
+            if (CreateLogFile() != 0) {
+                goto error;
+            }
+        } else {
+            std::string filename(AUDIT_LOG_DIRECTORY);
+            filename += m_fileNameMap.rbegin()->second;
+            m_outputStream.open(filename, std::ios_base::app);
+        }
+    }
+
+    return;
+
+error:
+    m_state = false;
+
+}
+
+AuditSmackLog::~AuditSmackLog(){}
+
+bool AuditSmackLog::Fail() const
+{
+    return !m_state;
+}
+
+void AuditSmackLog::SmackAudit(const char *message,
+                               const char *fileName,
+                               int line,
+                               const char *function)
+{
+    if (m_state) {
+        HandleWrite(message, fileName, line, function);
+    }
+}
+
+void AuditSmackLog::HandleWrite(const char *message,
+                                const char *filename,
+                                int line,
+                                const char *function)
+{
+    std::lock_guard<std::mutex> lock(m_writeMtx);
+    if (IsFileFull(m_outputStream)) {
+        if (CreateLogFile() != 0) {
+            m_state = false;
+            return;
+        }
+
+        if (m_fileNameMap.size() > m_filesCount) {
+            if (RemoveOldestLogFile() != 0) {
+                m_state = false;
+                return;
+            }
+        }
+    }
+
+    m_outputStream << std::string("[") <<
+        LocateSourceFileName(filename) << std::string(":") << line <<
+        std::string("] ") << function << std::string("(): ") << message << '\n';
+}
+
+int AuditSmackLog::CreateLogFile()
+{
+    time_t sec = time(NULL);
+    std::string fname(AUDIT_LOG_FILENAME_PREFIX);
+    std::string pathname(AUDIT_LOG_DIRECTORY);
+
+    fname += std::to_string(sec);
+    fname += ".log";
+    pathname += fname;
+
+    if (m_outputStream.is_open())
+        m_outputStream.close();
+
+    m_outputStream.open(pathname.c_str());
+
+    if (!m_outputStream) {
+        return -1;
+    }
+
+    if (smack_setlabel(pathname.c_str(),
+                       AUDIT_LOG_SMACK_LABEL.c_str(),
+                       SMACK_LABEL_ACCESS) != 0)  {
+        return -1;
+    }
+
+    m_fileNameMap.insert(std::make_pair(sec, fname));
+    return 0;
+}
+
+int AuditSmackLog::RemoveOldestLogFile()
+{
+    assert(m_fileNameMap.size() > 0);
+
+    auto it = m_fileNameMap.begin();
+    std::string filename(AUDIT_LOG_DIRECTORY);
+    filename += it->second;
+
+    if (unlink(filename.c_str()) == 0) {
+        m_fileNameMap.erase(it);
+        return 0;
+    }
+
+    return -1;
+}
+
+int AuditSmackLog::ParseConfig()
+{
+    struct stat sb;
+    if (stat(AUDIT_CONFIG_LOG_PATH.c_str(), &sb) != 0) {
+        return -1;
+    }
+
+    std::ifstream in(AUDIT_CONFIG_LOG_PATH + AUDIT_CONFIG_FILENAME,
+                     std::ios_base::in);
+    if (!in) {
+        return -1;
+    }
+
+    in >> m_filesCount >> m_fileMaxBytesSize;
+
+    if (in.fail()) {
+        return -1;
+    }
+
+    return (m_filesCount > 0 && m_fileMaxBytesSize > 0) ? 0 : -1;
+}
+
+int AuditSmackLog::ProcessLogDir()
+{
+    DIR *dir;
+    dirent *dp;
+
+    if ((dir = opendir(AUDIT_LOG_DIRECTORY.c_str())) == NULL) {
+        return -1;
+    }
+
+    while ((dp = readdir(dir)) != NULL) {
+        if (AUDIT_LOG_FILENAME_PREFIX.compare(0, std::string::npos,
+                                      dp->d_name,
+                                      AUDIT_LOG_FILENAME_PREFIX.size()) == 0) {
+            errno = 0;
+            char *pEnd;
+            time_t fUnxTime = static_cast<time_t>(
+                    strtoull(dp->d_name + AUDIT_LOG_FILENAME_PREFIX.size(),
+                             &pEnd, 10));
+
+            if (errno != 0) {
+                closedir(dir);
+                return -1;
+            }
+
+            m_fileNameMap.insert(
+                    std::make_pair(fUnxTime, std::string(dp->d_name)));
+        }
+    }
+
+    closedir(dir);
+
+    return 0;
+}
+
+bool AuditSmackLog::IsFileFull(std::ofstream &fs) const
+{
+    return fs.tellp() > m_fileMaxBytesSize;
+}
+
+void AuditSmackLog::Debug(const char *message UNUSED,
+                          const char *filename UNUSED,
+                          int line UNUSED,
+                          const char *function UNUSED)
+{
+}
+
+void AuditSmackLog::Info(const char *message UNUSED,
+                         const char *filename UNUSED,
+                         int line UNUSED,
+                         const char *function UNUSED)
+{
+}
+
+void AuditSmackLog::Warning(const char *message UNUSED,
+                            const char *filename UNUSED,
+                            int line UNUSED,
+                            const char *function UNUSED)
+{
+}
+
+void AuditSmackLog::Error(const char *message UNUSED,
+                          const char *filename UNUSED,
+                          int line UNUSED,
+                          const char *function UNUSED)
+{
+}
+
+void AuditSmackLog::Pedantic(const char *message UNUSED,
+                             const char *filename UNUSED,
+                             int line UNUSED,
+                             const char *function UNUSED)
+{
+}
+
+void AuditSmackLog::SecureDebug(const char *message UNUSED,
+                                const char *filename UNUSED,
+                                int line UNUSED,
+                                const char *function UNUSED)
+{
+}
+
+void AuditSmackLog::SecureInfo(const char *message UNUSED,
+                               const char *filename  UNUSED,
+                               int line  UNUSED,
+                               const char *function UNUSED)
+{
+}
+
+void AuditSmackLog::SecureWarning(const char *message UNUSED,
+                                  const char *filename UNUSED,
+                                  int line UNUSED,
+                                  const char *function UNUSED)
+{
+}
+
+void AuditSmackLog::SecureError(const char *message UNUSED,
+                                const char *filename UNUSED,
+                                int line UNUSED,
+                                const char *function UNUSED)
+{
+}
+
+} // namespace Log
+} // namespace SecurityServer
index 2f5f204..90f0713 100644 (file)
@@ -141,5 +141,12 @@ void DLOGLogProvider::SecureError(const char *message UNUSED,
         FormatMessage(message, filename, line, function).c_str());
 }
 
+void DLOGLogProvider::SmackAudit(const char *message UNUSED,
+                           const char *filename UNUSED,
+                           int line UNUSED,
+                           const char *function UNUSED)
+{
 }
+
+} // nemespace Log
 } // namespace SecurityServer
index 98fe7f6..a91cdb2 100644 (file)
@@ -26,6 +26,7 @@
 #include <dpl/singleton_impl.h>
 #include <dpl/log/dlog_log_provider.h>
 #include <dpl/log/old_style_log_provider.h>
+#include <dpl/log/audit-smack-log.h>
 
 IMPLEMENT_SINGLETON(SecurityServer::Log::LogSystem)
 
@@ -124,6 +125,13 @@ LogSystem::LogSystem() :
 #else // BUILD_TYPE_DEBUG
     AddProvider(new DLOGLogProvider());
 #endif // BUILD_TYPE_DEBUG
+
+    AuditSmackLog * smackLog = new AuditSmackLog();
+    if (smackLog->Fail()) {
+        delete smackLog;
+    } else {
+        AddProvider(smackLog);
+    }
 }
 
 LogSystem::~LogSystem()
@@ -275,5 +283,19 @@ void LogSystem::SecureWarning(const char *message,
         (*iterator)->SecureWarning(message, filename, line, function);
     }
 }
+
+void LogSystem::SmackAudit(const char *message,
+                     const char *fileName,
+                     int line,
+                     const char *function)
+{
+    for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin();
+         iterator != m_providers.end();
+         ++iterator)
+    {
+        (*iterator)->SmackAudit(message, fileName, line, function);
+    }
+}
+
 }
 } // namespace SecurityServer
index f59f40e..4c10749 100644 (file)
@@ -298,5 +298,16 @@ void OldStyleLogProvider::SecureError(const char *message,
 #endif
 }
 
+void OldStyleLogProvider::SmackAudit(const char *message,
+                               const char *fileName,
+                               int line,
+                               const char *function)
+{
+    (void)message;
+    (void)fileName;
+    (void)line;
+    (void)function;
+}
+
 }
 } // namespace SecurityServer
index 663fba1..e5fa207 100644 (file)
@@ -54,7 +54,6 @@ int server2(void) {
 //        echoService->Create();
 //        manager.RegisterSocketService(echoService);
 
-
         SecurityServer::CookieService *cookieService = new SecurityServer::CookieService;
         cookieService->Create();
         manager.RegisterSocketService(cookieService);
index 29c1b03..f6408d1 100644 (file)
@@ -313,11 +313,18 @@ bool CookieService::privilegeByCookieRequest(MessageBuffer &buffer, MessageBuffe
             Serialization::Serialize(send, (int)SECURITY_SERVER_API_SUCCESS);
         } else {
             subject = searchResult->smackLabel;
+            int retval;
 
-            if (smack_have_access(subject.c_str(), object.c_str(), access.c_str()) == 1)
+            if ((retval = smack_have_access(subject.c_str(), object.c_str(), access.c_str())) == 1)
                 Serialization::Serialize(send, (int)SECURITY_SERVER_API_SUCCESS);
-            else
+            else {
                 Serialization::Serialize(send, (int)SECURITY_SERVER_API_ERROR_ACCESS_DENIED);
+                LogSmackAudit("SS_SMACK: "
+                    << " subject=" << subject
+                    << ", object=" << object
+                    << ", access=" << access
+                    << ", result=" << retval);
+            }
         }
     } else {
         Serialization::Serialize(send, (int)SECURITY_SERVER_API_ERROR_NO_SUCH_COOKIE);
index 8fdafa3..a5fd4af 100644 (file)
@@ -97,7 +97,6 @@ bool PrivilegeByPidService::processOne(const ConnectionID &conn, MessageBuffer &
         LogDebug("SMACK is not available. Subject label has not been read.");
         retval = 1;
     }
-
 //    char *path = read_exe_path_from_proc(pid);
 //
 //    if (retval > 0)
@@ -120,6 +119,7 @@ bool PrivilegeByPidService::processOne(const ConnectionID &conn, MessageBuffer &
 //    if (path != NULL)
 //        free(path);
 
+
     if (retval == 1)   //there is permission
         retCode = SECURITY_SERVER_API_SUCCESS;
     else                //there is no permission
@@ -128,6 +128,21 @@ bool PrivilegeByPidService::processOne(const ConnectionID &conn, MessageBuffer &
     MessageBuffer sendBuffer;
     Serialization::Serialize(sendBuffer, retCode);
     m_serviceManager->Write(conn, sendBuffer.Pop());
+
+    if (retval != 1) {
+        char *path = read_exe_path_from_proc(pid);
+
+        LogSmackAudit("SS_SMACK: "
+            << "caller_pid=" << pid
+            << ", subject="  << subject
+            << ", object="   << object
+            << ", access="   << access_rights
+            << ", result="   << retval
+            << ", caller_path=" << (path ? path : ""));
+
+        free(path);
+    }
+
     return true;
 }