Source0: %{name}-%{version}.tar.gz
Source1: security-manager.manifest
Source3: libsecurity-manager-client.manifest
+Source4: libnss-security-manager.manifest
Requires: security-manager-policy
Requires: nether
Requires(post): sqlite3
%description -n libsecurity-manager-client-devel
Development files needed for using the security manager client
+%package -n libnss-security-manager
+Summary: Security Manager NSS library
+Group: Security/Libraries
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description -n libnss-security-manager
+Tizen Security Manager NSS library
+
%package policy
Summary: Security manager policy
Group: Security/Access Control
%setup -q
cp %{SOURCE1} .
cp %{SOURCE3} .
+cp %{SOURCE4} .
%build
%if 0%{?sec_build_binary_debug_enable}
mkdir -p %{buildroot}%{_datadir}/license
cp LICENSE %{buildroot}%{_datadir}/license/%{name}
cp LICENSE %{buildroot}%{_datadir}/license/libsecurity-manager-client
+cp LICENSE %{buildroot}%{_datadir}/license/libnss-security-manager
%make_install
mkdir -p %{buildroot}/%{_unitdir}/sockets.target.wants
mkdir -p %{buildroot}/%{_unitdir}/sysinit.target.wants
mkdir -p %{buildroot}/%{_unitdir}/basic.target.wants
+mkdir -p %{buildroot}/%{_unitdir}/dbus.service.wants
ln -s ../security-manager.socket %{buildroot}/%{_unitdir}/sockets.target.wants/security-manager.socket
ln -s ../security-manager-cleanup.service %{buildroot}/%{_unitdir}/sysinit.target.wants/security-manager-cleanup.service
ln -s ../security-manager-rules-loader.service %{buildroot}/%{_unitdir}/basic.target.wants/security-manager-rules-loader.service
+ln -s ../security-manager.service %{buildroot}/%{_unitdir}/dbus.service.wants/security-manager.service
mkdir -p %{buildroot}/%{TZ_SYS_DB}
touch %{buildroot}/%{TZ_SYS_DB}/.security-manager.db
%postun -n libsecurity-manager-client -p /sbin/ldconfig
+%post -n libnss-security-manager -p /sbin/ldconfig
+
+%postun -n libnss-security-manager -p /sbin/ldconfig
+
%post policy
%{_bindir}/security-manager-policy-reload
%{_includedir}/security-manager/*.h
%{_libdir}/pkgconfig/security-manager.pc
+%files -n libnss-security-manager
+%manifest libnss-security-manager.manifest
+%defattr(-,root,root,-)
+%%attr(-,root,root) %{_unitdir}/dbus.service.wants/security-manager.service
+%{_libdir}/libnss_securitymanager.so.*
+%{_datadir}/license/libnss-security-manager
+
%files -n security-manager-policy
%manifest %{name}.manifest
%{_datadir}/security-manager/policy
--- /dev/null
+SET(NSS_PLUGIN_VERSION_MAJOR 2)
+SET(NSS_PLUGIN_VERSION ${NSS_PLUGIN_VERSION_MAJOR}.0.0)
+
+SET(LIBRARY_FILE_NAME "nss_securitymanager")
+
+INCLUDE_DIRECTORIES(
+ ${INCLUDE_PATH}
+ ${CLIENT_PATH}/include
+ ${NSS_PATH}/include
+ ${DPL_PATH}/core/include
+ ${DPL_PATH}/log/include
+ )
+
+SET(NSS_SOURCES
+ ${NSS_PATH}/nss_securitymanager.cpp
+ )
+
+ADD_LIBRARY(${TARGET_NSS} SHARED ${NSS_SOURCES})
+
+SET_TARGET_PROPERTIES(${TARGET_NSS}
+ PROPERTIES
+ OUTPUT_NAME ${LIBRARY_FILE_NAME}
+ COMPILE_FLAGS "-D_GNU_SOURCE -fPIC -fvisibility=hidden"
+ SOVERSION ${NSS_PLUGIN_VERSION_MAJOR}
+ VERSION ${NSS_PLUGIN_VERSION}
+ )
+
+TARGET_LINK_LIBRARIES(${TARGET_NSS}
+ ${TARGET_CLIENT}
+ ${TARGET_COMMON}
+ )
+
+INSTALL(TARGETS ${TARGET_NSS} LIBRARY DESTINATION ${LIB_INSTALL_DIR} NAMELINK_SKIP)
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Rafal Krypa <r.krypa@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
+ *
+ * Security Manager NSS library
+ */
+/*
+ * @file nss_securitymanager.cpp
+ * @author Aleksander Zdyb <a.zdyb@samsung.com>
+ * @version 1.0
+ * @brief This file contains NSS library implementation for Security Manager
+ */
+
+#include <cerrno>
+#include <cstddef>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <nss.h>
+#include <unistd.h>
+#include <cstdlib>
+
+#include <vector>
+
+#include <security-manager.h>
+
+namespace {
+
+size_t getBufferSize()
+{
+ size_t max = 4096, tmp;
+ max = max < (tmp = sysconf(_SC_GETPW_R_SIZE_MAX)) ? tmp : max;
+ return max < (tmp = sysconf(_SC_GETGR_R_SIZE_MAX)) ? tmp : max;
+}
+
+} // anonymous namespace
+
+extern "C" {
+
+
+__attribute__((visibility("default")))
+enum nss_status _nss_securitymanager_initgroups_dyn(const char *user, gid_t group_gid, long int *start,
+ long int *size, gid_t **groupsp,
+ long int limit, int *errnop)
+{
+ try {
+ (void) group_gid;
+
+ int ret;
+ const static size_t BUFFER_SIZE = getBufferSize();
+ const static size_t MEMORY_LIMIT = BUFFER_SIZE << 3;
+ std::vector<char> buffer(BUFFER_SIZE);
+ passwd pwnambuffer;
+ passwd *pwnam = NULL;
+
+ do {
+ ret = TEMP_FAILURE_RETRY(getpwnam_r(user, &pwnambuffer, buffer.data(), buffer.size(), &pwnam));
+ if (ret == ERANGE && buffer.size() < MEMORY_LIMIT) {
+ buffer.resize(buffer.size() << 1);
+ continue;
+ }
+ } while (0);
+
+ if (ret == ERANGE) {
+ *errnop = ENOMEM;
+ return NSS_STATUS_UNAVAIL;
+ }
+
+ if (ret || pwnam == NULL) {
+ *errnop = ENOENT;
+ return NSS_STATUS_NOTFOUND;
+ }
+
+ char **groups;
+ size_t groupsCount;
+ ret = security_manager_groups_get_for_user(pwnam->pw_uid, &groups, &groupsCount);
+
+ if (ret == SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT) {
+ // If user is not managed by Security Manager, we want to apply all the groups
+ ret = security_manager_groups_get(&groups, &groupsCount);
+ }
+
+ if (ret == SECURITY_MANAGER_ERROR_MEMORY) {
+ *errnop = ENOMEM;
+ return NSS_STATUS_UNAVAIL;
+ }
+
+ if (ret == SECURITY_MANAGER_ERROR_ACCESS_DENIED) {
+ *errnop = EPERM;
+ return NSS_STATUS_UNAVAIL;
+ }
+
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ *errnop = ENOENT;
+ return NSS_STATUS_UNAVAIL;
+ }
+
+ std::vector<gid_t> result;
+
+ for (size_t i = 0; i < groupsCount; ++i) {
+ group *grnam = NULL;
+ group groupbuff;
+ do {
+ ret = TEMP_FAILURE_RETRY(getgrnam_r(groups[i], &groupbuff, buffer.data(), buffer.size(), &grnam));
+ if (ret == ERANGE && buffer.size() < MEMORY_LIMIT) {
+ buffer.resize(buffer.size() << 1);
+ continue;
+ }
+ } while(0);
+
+ if (ret == ERANGE) {
+ *errnop = ENOMEM;
+ return NSS_STATUS_UNAVAIL;
+ }
+
+ if (grnam)
+ result.push_back(grnam->gr_gid);
+ }
+
+ if (((*size) - (*start)) < static_cast<long int>(result.size())) {
+ long int required = (*start) + result.size();
+ // value bigger is the lowest power of 2 that is bigger than required value
+ long int bigger = 1 << ((sizeof(unsigned long) << 3) - __builtin_clzl(static_cast<unsigned long>(required)));
+
+ gid_t *ptr = static_cast<gid_t*>(realloc(*groupsp, sizeof(gid_t) * (bigger)));
+ if (!ptr) {
+ *errnop = ENOMEM;
+ return NSS_STATUS_UNAVAIL;
+ }
+ *size = bigger;
+ *groupsp = ptr;
+ }
+
+ for (auto e : result) {
+ (*groupsp)[(*start)++] = e;
+ if (limit > 0 && (*start) >= limit)
+ break;
+ }
+
+ } catch (...) {
+ // We are leaving c++ code and going to pure c so this
+ // Pokemon catch (catch them all) is realy required here.
+ return NSS_STATUS_UNAVAIL;
+ }
+ return NSS_STATUS_SUCCESS;
+}
+
+} /* extern "C" */