diff options
author | jooseong.lee <jooseong.lee@samsung.com> | 2016-02-19 11:56:25 +0900 |
---|---|---|
committer | jooseong.lee <jooseong.lee@samsung.com> | 2016-02-19 14:49:00 +0900 |
commit | 360f39f1a289cf405777c85e9eaf66eff6d3286e (patch) | |
tree | 7c87fe356381c8a7ed3671b5ca7abcb72dceae66 | |
parent | 7c84c139c757e14a65f5e336ef6bb0d565c83575 (diff) | |
download | auth-fw-360f39f1a289cf405777c85e9eaf66eff6d3286e.tar.gz auth-fw-360f39f1a289cf405777c85e9eaf66eff6d3286e.tar.bz2 auth-fw-360f39f1a289cf405777c85e9eaf66eff6d3286e.zip |
Implement authentication service
* Authentication-server (password check/set/recovery)
* Authentication-server-admin (password reset)
* Authenticate each user via password
Change-Id: I8c524fe1bce8df4aa68c0ca28f2c19f96e8bb6fb
Signed-off-by: jooseong.lee <jooseong.lee@samsung.com>
85 files changed, 9186 insertions, 0 deletions
@@ -0,0 +1 @@ +Jooseong Lee <jooseong.lee@samsung.com> diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b05761b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,74 @@ +# Copyright (c) 2011-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 +# @brief +# +############################# Check minimum CMake version ##################### + +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT("auth-fw") + +############################# cmake packages ################################## + +INCLUDE(FindPkgConfig) + +############################# compiler flags ################################## + +SET(CMAKE_C_FLAGS_PROFILING "-g -O0 -pg -Wp,-U_FORTIFY_SOURCE") +SET(CMAKE_CXX_FLAGS_PROFILING "-g -std=c++0x -O0 -pg -Wp,-U_FORTIFY_SOURCE") +SET(CMAKE_C_FLAGS_DEBUG "-g -O0 -ggdb -Wp,-U_FORTIFY_SOURCE") +SET(CMAKE_CXX_FLAGS_DEBUG "-g -std=c++0x -O0 -ggdb -Wp,-U_FORTIFY_SOURCE") +SET(CMAKE_C_FLAGS_RELEASE "-g -O2") +SET(CMAKE_CXX_FLAGS_RELEASE "-g -std=c++0x -O2") +SET(CMAKE_C_FLAGS_CCOV "-g -O2 --coverage") +SET(CMAKE_CXX_FLAGS_CCOV "-g -std=c++0x -O2 --coverage") + +# If supported for the target machine, emit position-independent code,suitable +# for dynamic linking and avoiding any limit on the size of the global offset +# table. This option makes a difference on the m68k, PowerPC and SPARC. +# (BJ: our ARM too?) +ADD_DEFINITIONS("-fPIC") + +# Set compiler warning flags +#ADD_DEFINITIONS("-Werror") # Make all warnings into errors. +ADD_DEFINITIONS("-Wall") # Generate all warnings +ADD_DEFINITIONS("-Wextra") # Generate even more extra warnings + +STRING(REGEX MATCH "([^.]*)" API_VERSION "${VERSION}") +ADD_DEFINITIONS("-DAPI_VERSION=\"$(API_VERSION)\"") +ADD_DEFINITIONS("-DSMACK_ENABLED") +ADD_DEFINITIONS("-DTIZEN_VERSION=${TIZEN_VERSION}") +ADD_DEFINITIONS("-DDLOG_WARN_ENABLED") +ADD_DEFINITIONS("-DDLOG_ERROR_ENABLED") +SET(CACHE_DIR \"/opt/data/privilege-control-cache\") +ADD_DEFINITIONS("-DCACHE_DIR=${CACHE_DIR}") + +IF (CMAKE_BUILD_TYPE MATCHES "DEBUG") + ADD_DEFINITIONS("-DBUILD_TYPE_DEBUG") + ADD_DEFINITIONS("-DDLOG_DEBUG_ENABLED") +ENDIF (CMAKE_BUILD_TYPE MATCHES "DEBUG") + +INSTALL(FILES + ${CMAKE_SOURCE_DIR}/packaging/authentication-server.manifest + ${CMAKE_SOURCE_DIR}/packaging/libauthentication-server-client.manifest + ${CMAKE_SOURCE_DIR}/packaging/libauthentication-server-client-admin.manifest + DESTINATION + /usr/share +) + +ADD_SUBDIRECTORY(src) +ADD_SUBDIRECTORY(pkgconfig) +ADD_SUBDIRECTORY(systemd) @@ -0,0 +1,203 @@ +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. @@ -0,0 +1 @@ +README for authentication server project diff --git a/packaging/authentication-server.manifest b/packaging/authentication-server.manifest new file mode 100644 index 0000000..a76fdba --- /dev/null +++ b/packaging/authentication-server.manifest @@ -0,0 +1,5 @@ +<manifest> + <request> + <domain name="_" /> + </request> +</manifest> diff --git a/packaging/authentication-server.spec b/packaging/authentication-server.spec new file mode 100644 index 0000000..0ddd2b0 --- /dev/null +++ b/packaging/authentication-server.spec @@ -0,0 +1,164 @@ +Name: authentication-server +Summary: Authentication server +Version: 0.0.1 +Release: 1 +Group: System/Security +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz +BuildRequires: cmake +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(openssl) +BuildRequires: pkgconfig(libsmack) +BuildRequires: pkgconfig(libsystemd-daemon) +BuildRequires: pkgconfig(libtzplatform-config) +%{?systemd_requires} + +%description +Authentication server with client libraries + +%package -n libauthentication-server-client +Summary: Authentication server (client) +Group: Development/Libraries +Requires: authentication-server = %{version}-%{release} +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig + +%description -n libauthentication-server-client +Authentication server package (client) + +%package -n libauthentication-server-client-admin +Summary: Authentication server (client-admin) +Group: Development/Libraries +Requires: authentication-server = %{version}-%{release} +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig + +%description -n libauthentication-server-client-admin +Authentication server package (client-admin) + +%package -n libauthentication-server-client-devel +Summary: Authentication server (client-devel) +Group: Development/Libraries +Requires: libauthentication-server-client = %{version}-%{release} +Requires: libauthentication-server-client-admin = %{version}-%{release} + +%description -n libauthentication-server-client-devel +Authentication server package (client-devel) + +%package -n authentication-server-devel +Summary: Authentication (Development) +Group: Development/Libraries +Requires: authentication-server = %{version}-%{release} + +%description -n authentication-server-devel +Authentication server package (Development) + +%prep +%setup -q + +%build + +export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE" +export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE" +export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE" +export LDFLAGS+="-Wl,--rpath=%{_libdir}" + +%cmake . -DVERSION=%{version} \ + -DCMAKE_BUILD_TYPE=%{?build_type:%build_type}%{!?build_type:RELEASE} \ + -DCMAKE_VERBOSE_MAKEFILE=ON + +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +mkdir -p %{buildroot}/usr/share/license +cp LICENSE %{buildroot}/usr/share/license/%{name} +cp LICENSE %{buildroot}/usr/share/license/libauthentication-server-client +cp LICENSE %{buildroot}/usr/share/license/libauthentication-server-client-admin +%make_install + +mkdir -p %{buildroot}/usr/lib/systemd/system/multi-user.target.wants +mkdir -p %{buildroot}/usr/lib/systemd/system/sockets.target.wants +mkdir -p %{buildroot}/usr/lib/systemd/system/basic.target.wants +ln -s ../authentication-server.service %{buildroot}/usr/lib/systemd/system/multi-user.target.wants/authentication-server.service +ln -s ../authentication-server-passwd-check.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/authentication-server-passwd-check.socket +ln -s ../authentication-server-passwd-set.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/authentication-server-passwd-set.socket +ln -s ../authentication-server-passwd-reset.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/authentication-server-passwd-reset.socket +ln -s ../authentication-server-passwd-policy.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/authentication-server-passwd-policy.socket + +%clean +rm -rf %{buildroot} + +%post +systemctl daemon-reload +if [ $1 = 1 ]; then + # installation + systemctl start authentication-server.service +fi + +if [ $1 = 2 ]; then + # update + systemctl restart authentication-server.service +fi + +%preun +if [ $1 = 0 ]; then + # unistall + systemctl stop authentication-server.service +fi + +%postun +if [ $1 = 0 ]; then + # unistall + systemctl daemon-reload +fi + +%post -n libauthentication-server-client -p /sbin/ldconfig + +%postun -n libauthentication-server-client -p /sbin/ldconfig + +%post -n libauthentication-server-client-admin -p /sbin/ldconfig + +%postun -n libauthentication-server-client-admin -p /sbin/ldconfig + +%files -n authentication-server +%manifest %{_datadir}/authentication-server.manifest +%attr(755,root,root) /usr/bin/authentication-server +%{_libdir}/libauthentication-server-commons.so.* +%attr(-,root,root) /usr/lib/systemd/system/multi-user.target.wants/authentication-server.service +%attr(-,root,root) /usr/lib/systemd/system/authentication-server.service +%attr(-,root,root) /usr/lib/systemd/system/authentication-server.target +%attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/authentication-server-passwd-check.socket +%attr(-,root,root) /usr/lib/systemd/system/authentication-server-passwd-check.socket +%attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/authentication-server-passwd-set.socket +%attr(-,root,root) /usr/lib/systemd/system/authentication-server-passwd-set.socket +%attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/authentication-server-passwd-reset.socket +%attr(-,root,root) /usr/lib/systemd/system/authentication-server-passwd-reset.socket +%attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/authentication-server-passwd-policy.socket +%attr(-,root,root) /usr/lib/systemd/system/authentication-server-passwd-policy.socket + +%{_datadir}/license/%{name} + +%files -n libauthentication-server-client +%manifest %{_datadir}/libauthentication-server-client.manifest +%defattr(-,root,root,-) +%{_libdir}/libauthentication-server-client.so.* +%{_datadir}/license/libauthentication-server-client + +%files -n libauthentication-server-client-admin +%manifest %{_datadir}/libauthentication-server-client-admin.manifest +%defattr(-,root,root,-) +%{_libdir}/libauthentication-server-client-admin.so.* +%{_datadir}/license/libauthentication-server-client-admin + +%files -n libauthentication-server-client-devel +%defattr(-,root,root,-) +%{_libdir}/libauthentication-server-client.so +%{_libdir}/libauthentication-server-client-admin.so +%{_libdir}/libauthentication-server-commons.so +/usr/include/authentication-server/auth-passwd.h +/usr/include/authentication-server/auth-passwd-admin.h +/usr/include/authentication-server/auth-passwd-error.h +/usr/include/authentication-server/auth-passwd-policy-types.h +%{_libdir}/pkgconfig/*.pc + diff --git a/packaging/libauthentication-server-client-admin.manifest b/packaging/libauthentication-server-client-admin.manifest new file mode 100644 index 0000000..a76fdba --- /dev/null +++ b/packaging/libauthentication-server-client-admin.manifest @@ -0,0 +1,5 @@ +<manifest> + <request> + <domain name="_" /> + </request> +</manifest> diff --git a/packaging/libauthentication-server-client.manifest b/packaging/libauthentication-server-client.manifest new file mode 100644 index 0000000..a76fdba --- /dev/null +++ b/packaging/libauthentication-server-client.manifest @@ -0,0 +1,5 @@ +<manifest> + <request> + <domain name="_" /> + </request> +</manifest> diff --git a/pkgconfig/CMakeLists.txt b/pkgconfig/CMakeLists.txt new file mode 100644 index 0000000..a3ef112 --- /dev/null +++ b/pkgconfig/CMakeLists.txt @@ -0,0 +1,28 @@ +# Copyright (c) 2011 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) +# @brief +# + +CONFIGURE_FILE(authentication-server.pc.in authentication-server.pc @ONLY) +CONFIGURE_FILE(authentication-server-admin.pc.in authentication-server-admin.pc @ONLY) + +INSTALL(FILES + ${CMAKE_BINARY_DIR}/pkgconfig/authentication-server.pc + ${CMAKE_BINARY_DIR}/pkgconfig/authentication-server-admin.pc + DESTINATION + ${LIB_INSTALL_DIR}/pkgconfig + ) diff --git a/pkgconfig/authentication-server-admin.pc.in b/pkgconfig/authentication-server-admin.pc.in new file mode 100644 index 0000000..b10e320 --- /dev/null +++ b/pkgconfig/authentication-server-admin.pc.in @@ -0,0 +1,11 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=@LIB_INSTALL_DIR@ +includedir=${prefix}/include + +Name: authentication-server-admin +Description: Authentication server admin +Version: 1.0.1 +Requires: +Libs: -L${libdir} -lauthentication-server-client-admin -lauthentication-server-commons +Cflags: -I${includedir}/authentication-server diff --git a/pkgconfig/authentication-server.pc.in b/pkgconfig/authentication-server.pc.in new file mode 100644 index 0000000..da2e4e9 --- /dev/null +++ b/pkgconfig/authentication-server.pc.in @@ -0,0 +1,11 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=@LIB_INSTALL_DIR@ +includedir=${prefix}/include + +Name: authentication-server +Description: Authentication server +Version: 1.0.1 +Requires: +Libs: -L${libdir} -lauthentication-server-client -lauthentication-server-commons +Cflags: -I${includedir}/authentication-server diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..0319df7 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,16 @@ +SET(INCLUDE_PATH ${PROJECT_SOURCE_DIR}/src/include) +SET(COMMON_PATH ${PROJECT_SOURCE_DIR}/src/common) +SET(CLIENT_PATH ${PROJECT_SOURCE_DIR}/src/client) +SET(SERVER_PATH ${PROJECT_SOURCE_DIR}/src/server) +SET(PLUGIN_PATH ${PROJECT_SOURCE_DIR}/src/plugin) +SET(DPL_PATH ${PROJECT_SOURCE_DIR}/src/dpl) + +SET(TARGET_SERVER "authentication-server") +SET(TARGET_CLIENT "authentication-server-client") +SET(TARGET_CLIENT_ADMIN "authentication-server-client-admin") +SET(TARGET_COMMON "authentication-server-commons") + +ADD_SUBDIRECTORY(include) +ADD_SUBDIRECTORY(common) +ADD_SUBDIRECTORY(client) +ADD_SUBDIRECTORY(server) diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt new file mode 100644 index 0000000..31a4bf9 --- /dev/null +++ b/src/client/CMakeLists.txt @@ -0,0 +1,62 @@ +SET(AUTH_CLIENT_VERSION_MAJOR 1) +SET(AUTH_CLIENT_VERSION ${AUTH_CLIENT_VERSION_MAJOR}.0.1) + +INCLUDE_DIRECTORIES( + ${INCLUDE_PATH} + ${COMMON_PATH}/include + ${CLIENT_PATH}/include + ${DPL_PATH}/core/include + ${DPL_PATH}/log/include + ) + +SET(CLIENT_SOURCES + ${CLIENT_PATH}/client-common.cpp + ${CLIENT_PATH}/client-password.cpp + ) + +ADD_LIBRARY(${TARGET_CLIENT} SHARED ${CLIENT_SOURCES}) + +SET_TARGET_PROPERTIES( + ${TARGET_CLIENT} + PROPERTIES + COMPILE_FLAGS "-D_GNU_SOURCE -fPIC -fvisibility=hidden" + SOVERSION ${AUTH_CLIENT_VERSION_MAJOR} + VERSION ${AUTH_CLIENT_VERSION} + ) + +TARGET_LINK_LIBRARIES(${TARGET_CLIENT} + ${TARGET_COMMON} + ) + +INSTALL(TARGETS ${TARGET_CLIENT} DESTINATION ${LIB_INSTALL_DIR}) + +################################################################################ + +INCLUDE_DIRECTORIES( + ${INCLUDE_PATH} + ${COMMON_PATH}/include + ${CLIENT_PATH}/include + ${DPL_PATH}/core/include + ${DPL_PATH}/log/include + ) + +SET(CLIENT_ADMIN_SOURCES + ${CLIENT_PATH}/client-common.cpp + ${CLIENT_PATH}/client-password-admin.cpp + ) + +ADD_LIBRARY(${TARGET_CLIENT_ADMIN} SHARED ${CLIENT_ADMIN_SOURCES}) + +SET_TARGET_PROPERTIES( + ${TARGET_CLIENT_ADMIN} + PROPERTIES + COMPILE_FLAGS "-D_GNU_SOURCE -fPIC -fvisibility=hidden" + SOVERSION ${AUTH_CLIENT_VERSION_MAJOR} + VERSION ${AUTH_CLIENT_VERSION} + ) + +TARGET_LINK_LIBRARIES(${TARGET_CLIENT_ADMIN} + ${TARGET_COMMON} + ) + +INSTALL(TARGETS ${TARGET_CLIENT_ADMIN} DESTINATION ${LIB_INSTALL_DIR}) diff --git a/src/client/client-common.cpp b/src/client/client-common.cpp new file mode 100644 index 0000000..ff811ce --- /dev/null +++ b/src/client/client-common.cpp @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file client-common.cpp + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + * @brief This file is implementation of client-common functions. + */ + +#include <fcntl.h> +#include <poll.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> + +#include <dpl/log/log.h> +#include <dpl/serialization.h> +#include <dpl/singleton.h> +#include <dpl/singleton_safe_impl.h> + +#include <error-description.h> +#include <message-buffer.h> +#include <auth-passwd.h> +#include <auth-passwd-admin.h> +#include <client-common.h> + +IMPLEMENT_SAFE_SINGLETON(AuthPasswd::Log::LogSystem); + +namespace { + +const int POLL_TIMEOUT = 300000; + +void authPasswdClientEnableLogSystem(void) { + AuthPasswd::Singleton<AuthPasswd::Log::LogSystem>::Instance().SetTag("AUTH_PASSWD_CLIENT"); +} + +int waitForSocket(int sock, int event, int timeout) { + int retval; + pollfd desc[1]; + desc[0].fd = sock; + desc[0].events = event; + + while((-1 == (retval = poll(desc, 1, timeout))) && (errno == EINTR)) { + timeout >>= 1; + errno = 0; + } + + if (0 == retval) { + LogDebug("Poll timeout"); + } else if (-1 == retval) { + int err = errno; + LogError("Error in poll: " << AuthPasswd::errnoToString(err)); + } + return retval; +} + +} // namespace anonymous + +namespace AuthPasswd { + + +int SockRAII::Connect(char const * const interface) { + sockaddr_un clientAddr; + int flags; + + if (m_sock != -1) // guard + close(m_sock); + + m_sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (m_sock < 0) { + int err = errno; + LogError("Error creating socket: " << AuthPasswd::errnoToString(err)); + return AUTH_PASSWD_API_ERROR_SOCKET; + } + + if ((flags = fcntl(m_sock, F_GETFL, 0)) < 0 || + fcntl(m_sock, F_SETFL, flags | O_NONBLOCK) < 0) + { + int err = errno; + LogError("Error in fcntl: " << AuthPasswd::errnoToString(err)); + return AUTH_PASSWD_API_ERROR_SOCKET; + } + + memset(&clientAddr, 0, sizeof(clientAddr)); + + clientAddr.sun_family = AF_UNIX; + + if (strlen(interface) >= sizeof(clientAddr.sun_path)) { + LogError("Error: interface name " << interface << "is too long. Max len is:" << sizeof(clientAddr.sun_path)); + return AUTH_PASSWD_API_ERROR_SOCKET; + } + + strcpy(clientAddr.sun_path, interface); + + LogDebug("ClientAddr.sun_path = " << interface); + + int retval = TEMP_FAILURE_RETRY(connect(m_sock, (struct sockaddr*)&clientAddr, SUN_LEN(&clientAddr))); + if ((retval == -1) && (errno == EINPROGRESS)) { + if (0 >= waitForSocket(m_sock, POLLOUT, POLL_TIMEOUT)) { + LogError("Error in waitForSocket."); + return AUTH_PASSWD_API_ERROR_SOCKET; + } + int error = 0; + size_t len = sizeof(error); + retval = getsockopt(m_sock, SOL_SOCKET, SO_ERROR, &error, &len); + + if (-1 == retval) { + int err = errno; + LogError("Error in getsockopt: " << AuthPasswd::errnoToString(err)); + return AUTH_PASSWD_API_ERROR_SOCKET; + } + + if (error == EACCES) { + LogError("Access denied"); + return AUTH_PASSWD_API_ERROR_ACCESS_DENIED; + } + + if (error != 0) { + LogError("Error in connect: " << AuthPasswd::errnoToString(error)); + return AUTH_PASSWD_API_ERROR_SOCKET; + } + + return AUTH_PASSWD_API_SUCCESS; + } + + if (-1 == retval) { + int err = errno; + LogError("Error connecting socket: " << AuthPasswd::errnoToString(err)); + if (err == EACCES) + return AUTH_PASSWD_API_ERROR_ACCESS_DENIED; + return AUTH_PASSWD_API_ERROR_SOCKET; + } + + return AUTH_PASSWD_API_SUCCESS; +} + +int sendToServerWithFd(int fd, const RawBuffer &send, MessageBuffer &recv) { + ssize_t done = 0; + char buffer[2048]; + while ((send.size() - done) > 0) { + if (0 >= waitForSocket(fd, POLLOUT, POLL_TIMEOUT)) { + LogError("Error in poll(POLLOUT)"); + return AUTH_PASSWD_API_ERROR_SOCKET; + } + ssize_t temp = TEMP_FAILURE_RETRY(::send(fd, &send[done], send.size() - done, MSG_NOSIGNAL)); + if (-1 == temp) { + int err = errno; + LogError("Error in send: " << errnoToString(err)); + return AUTH_PASSWD_API_ERROR_SOCKET; + } + done += temp; + } + + do { + if (0 >= waitForSocket(fd, POLLIN, POLL_TIMEOUT)) { + LogError("Error in poll(POLLIN)"); + return AUTH_PASSWD_API_ERROR_SOCKET; + } + ssize_t temp = TEMP_FAILURE_RETRY(::recv(fd, buffer, 2048, 0)); + if (-1 == temp) { + int err = errno; + LogError("Error in recv: " << errnoToString(err)); + return AUTH_PASSWD_API_ERROR_SOCKET; + } + + if (0 == temp) { + LogError("Read return 0/Connection closed by server(?)"); + return AUTH_PASSWD_API_ERROR_SOCKET; + } + + RawBuffer raw(buffer, buffer+temp); + recv.Push(raw); + } while(!recv.Ready()); + return AUTH_PASSWD_API_SUCCESS; +} + +int sendToServer(char const * const interface, const RawBuffer &send, MessageBuffer &recv) { + int ret; + SockRAII sock; + + if (AUTH_PASSWD_API_SUCCESS != (ret = sock.Connect(interface))) { + LogError("Error in SockRAII"); + return ret; + } + + return sendToServerWithFd(sock.Get(), send, recv); +} + +int sendToServerAncData(char const * const interface, const RawBuffer &send, struct msghdr &hdr) { + int ret; + SockRAII sock; + ssize_t done = 0; + + if (AUTH_PASSWD_API_SUCCESS != (ret = sock.Connect(interface))) { + LogError("Error in SockRAII"); + return ret; + } + + while ((send.size() - done) > 0) { + if (0 >= waitForSocket(sock.Get(), POLLOUT, POLL_TIMEOUT)) { + LogError("Error in poll(POLLOUT)"); + return AUTH_PASSWD_API_ERROR_SOCKET; + } + ssize_t temp = TEMP_FAILURE_RETRY(write(sock.Get(), &send[done], send.size() - done)); + if (-1 == temp) { + int err = errno; + LogError("Error in write: " << errnoToString(err)); + return AUTH_PASSWD_API_ERROR_SOCKET; + } + done += temp; + } + + if (0 >= waitForSocket(sock.Get(), POLLIN, POLL_TIMEOUT)) { + LogError("Error in poll(POLLIN)"); + return AUTH_PASSWD_API_ERROR_SOCKET; + } + + ssize_t temp = TEMP_FAILURE_RETRY(recvmsg(sock.Get(), &hdr, MSG_CMSG_CLOEXEC)); + + if (temp < 0) { + int err = errno; + LogError("Error in recvmsg(): " << errnoToString(err) << " errno: " << err); + return AUTH_PASSWD_API_ERROR_SOCKET; + } + + if (0 == temp) { + LogError("Read return 0/Connection closed by server(?)"); + return AUTH_PASSWD_API_ERROR_SOCKET; + } + + return AUTH_PASSWD_API_SUCCESS; +} + +int try_catch(const std::function<int()>& func) +{ + try { + return func(); + } catch (MessageBuffer::Exception::Base &e) { + LogError("AuthPasswd::MessageBuffer::Exception " << e.DumpToString()); + } catch (std::bad_alloc &e) { + LogError("Memory allocation failed " << e.what()); + return AUTH_PASSWD_API_ERROR_OUT_OF_MEMORY; + } catch (std::exception &e) { + LogError("STD exception " << e.what()); + } catch (...) { + LogError("Unknown exception occured"); + } + return AUTH_PASSWD_API_ERROR_UNKNOWN; +} + +} // namespace AuthPasswd + +static void init_lib(void) __attribute__ ((constructor)); +static void init_lib(void) +{ + authPasswdClientEnableLogSystem(); +} + +static void fini_lib(void) __attribute__ ((destructor)); +static void fini_lib(void) +{ + +} + diff --git a/src/client/client-password-admin.cpp b/src/client/client-password-admin.cpp new file mode 100644 index 0000000..8a4dcbf --- /dev/null +++ b/src/client/client-password-admin.cpp @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2016 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file client-password-admin.cpp + * @author Jooseong Lee (jooseong.lee@samsung.com) + * @version 1.0 + * @brief This file contains implementation of password functions. + */ + +#include <cstring> + +#include <dpl/log/log.h> +#include <dpl/exception.h> + +#include <message-buffer.h> +#include <client-common.h> +#include <protocols.h> +#include <policy.h> + +#include <auth-passwd-admin.h> + +namespace { + +const char *NO_PASSWORD = ""; + +inline bool isPasswordIncorrect(const char* pwd) +{ + // NULL means that password must be cancelled. + return (pwd && (strlen(pwd) == 0 || strlen(pwd) > AuthPasswd::MAX_PASSWORD_LEN)); +} + +} // namespace anonymous + +AUTH_PASSWD_API +int auth_passwd_reset_passwd(const password_type passwd_type, + const uid_t uid, + const char *new_passwd) +{ + using namespace AuthPasswd; + + return try_catch([&] { + if (isPasswordIncorrect(new_passwd)) { + LogError("Wrong input param."); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + + if (!new_passwd) { + new_passwd = NO_PASSWORD; + } + + MessageBuffer send, recv; + + Serialization::Serialize(send, static_cast<int>(PasswordHdrs::HDR_RST_PASSWD)); + Serialization::Serialize(send, passwd_type); + Serialization::Serialize(send, uid); + Serialization::Serialize(send, std::string(new_passwd)); + + int retCode = sendToServer(SERVICE_SOCKET_PASSWD_RESET, send.Pop(), recv); + if (AUTH_PASSWD_API_SUCCESS != retCode) { + LogError("Error in sendToServer. Error code: " << retCode); + return retCode; + } + + Deserialization::Deserialize(recv, retCode); + + return retCode; + }); +} + +AUTH_PASSWD_API +int auth_passwd_new_policy(policy_h **pp_policy) +{ + if (!pp_policy) + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + + try { + *pp_policy = new policy_h; + + } catch (std::bad_alloc& ex) { + return AUTH_PASSWD_API_ERROR_OUT_OF_MEMORY; + } + return AUTH_PASSWD_API_SUCCESS; +} + +AUTH_PASSWD_API +int auth_passwd_set_user(policy_h *p_policy, const uid_t uid) +{ + if (!p_policy) + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + + p_policy->uid = uid; + return AUTH_PASSWD_API_SUCCESS; +} + +AUTH_PASSWD_API +int auth_passwd_set_max_attempts(policy_h *p_policy, const unsigned int max_attempts) +{ + if (!p_policy) + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + + p_policy->maxAttempts = max_attempts; + return AUTH_PASSWD_API_SUCCESS; +} + +AUTH_PASSWD_API +int auth_passwd_set_validity(policy_h *p_policy, const unsigned int valid_days) +{ + if (!p_policy) + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + + p_policy->validPeriod = valid_days; + return AUTH_PASSWD_API_SUCCESS; +} + +AUTH_PASSWD_API +int auth_passwd_set_history_size(policy_h *p_policy, const unsigned int history_size) +{ + if (!p_policy) + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + + p_policy->historySize = history_size; + return AUTH_PASSWD_API_SUCCESS; +} + +AUTH_PASSWD_API +int auth_passwd_set_min_length(policy_h *p_policy, const unsigned int min_length) +{ + if (!p_policy) + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + + p_policy->minLength = min_length; + return AUTH_PASSWD_API_SUCCESS; +} + +AUTH_PASSWD_API +int auth_passwd_set_quality(policy_h *p_policy, password_quality_type quality_type) +{ + if (!p_policy) + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + + p_policy->qualityType = quality_type; + return AUTH_PASSWD_API_SUCCESS; +} + +AUTH_PASSWD_API +int auth_passwd_set_policy(policy_h *p_policy) +{ + using namespace AuthPasswd; + + return try_catch([&] { + if (!p_policy) { + LogError("Wrong input param."); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + + MessageBuffer send, recv; + + Serialization::Serialize(send, static_cast<int>(PasswordHdrs::HDR_SET_PASSWD_POLICY)); + Serialization::Serialize(send, p_policy); + + int retCode = sendToServer(SERVICE_SOCKET_PASSWD_POLICY, send.Pop(), recv); + if (AUTH_PASSWD_API_SUCCESS != retCode) { + LogError("Error in sendToServer. Error code: " << retCode); + return retCode; + } + + Deserialization::Deserialize(recv, retCode); + + return retCode; + }); +} + +AUTH_PASSWD_API +void auth_passwd_free_policy(policy_h *p_policy) +{ + delete p_policy; +} diff --git a/src/client/client-password.cpp b/src/client/client-password.cpp new file mode 100644 index 0000000..aad13c4 --- /dev/null +++ b/src/client/client-password.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file client-password.cpp + * @author Zbigniew Jasinski (z.jasinski@samsung.com) + * @author Lukasz Kostyra (l.kostyra@partner.samsung.com) + * @author Jooseong Lee (jooseong.lee@samsung.com) + * @version 1.0 + * @brief This file contains implementation of password functions. + */ + +#include <cstring> + +#include <dpl/log/log.h> +#include <dpl/exception.h> + +#include <message-buffer.h> +#include <client-common.h> +#include <policy.h> +#include <protocols.h> + +#include <auth-passwd.h> + +namespace { + +const char *NO_PASSWORD = ""; + +inline bool isPasswordIncorrect(const char* passwd) +{ + // NULL means that password must be cancelled. + return (passwd && (strlen(passwd) == 0 || strlen(passwd) > AuthPasswd::MAX_PASSWORD_LEN)); +} + +} // namespace anonymous + +AUTH_PASSWD_API +int auth_passwd_check_passwd(const password_type passwd_type, + const char *passwd, + unsigned int *current_attempts, + unsigned int *max_attempts, + unsigned int *valid_secs) +{ + using namespace AuthPasswd; + + return try_catch([&] { + if (isPasswordIncorrect(passwd) || + current_attempts == NULL || max_attempts == NULL || valid_secs == NULL) { + LogError("Wrong input param"); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + + if (!passwd) { + passwd = NO_PASSWORD; + } + + MessageBuffer send, recv; + + *current_attempts = 0; + *max_attempts = 0; + *valid_secs = 0; + + Serialization::Serialize(send, static_cast<int>(PasswordHdrs::HDR_CHK_PASSWD)); + Serialization::Serialize(send, passwd_type); + + //Clear pwd memory + std::string passwd_str(passwd); + Serialization::Serialize(send, passwd_str); + passwd_str.clear(); + + int retCode = sendToServer(SERVICE_SOCKET_PASSWD_CHECK, send.Pop(), recv); + if (AUTH_PASSWD_API_SUCCESS != retCode) { + LogDebug("Error in sendToServer. Error code: " << retCode); + return retCode; + } + + Deserialization::Deserialize(recv, retCode); + + switch (retCode) { + case AUTH_PASSWD_API_ERROR_PASSWORD_MISMATCH: + case AUTH_PASSWD_API_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED: + case AUTH_PASSWD_API_ERROR_PASSWORD_EXPIRED: + case AUTH_PASSWD_API_SUCCESS: + Deserialization::Deserialize(recv, *current_attempts); + Deserialization::Deserialize(recv, *max_attempts); + Deserialization::Deserialize(recv, *valid_secs); + break; + default: + break; + } + + return retCode; + }); +} + +AUTH_PASSWD_API +int auth_passwd_check_passwd_state(const password_type passwd_type, + unsigned int *current_attempts, + unsigned int *max_attempts, + unsigned int *valid_secs) +{ + using namespace AuthPasswd; + + return try_catch([&] { + if (NULL == current_attempts || NULL == max_attempts || + NULL == valid_secs) { + + LogError("Wrong input param"); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + + MessageBuffer send, recv; + + *current_attempts = 0; + *max_attempts = 0; + *valid_secs = 0; + + Serialization::Serialize(send, static_cast<int>(PasswordHdrs::HDR_CHK_PASSWD_STATE)); + Serialization::Serialize(send, passwd_type); + + int retCode = sendToServer(SERVICE_SOCKET_PASSWD_CHECK, send.Pop(), recv); + if (AUTH_PASSWD_API_SUCCESS != retCode) { + LogDebug("Error in sendToServer. Error code: " << retCode); + return retCode; + } + + Deserialization::Deserialize(recv, retCode); + + if(retCode == AUTH_PASSWD_API_SUCCESS) { + Deserialization::Deserialize(recv, *current_attempts); + Deserialization::Deserialize(recv, *max_attempts); + Deserialization::Deserialize(recv, *valid_secs); + } + + return retCode; + }); +} + +AUTH_PASSWD_API +int auth_passwd_check_passwd_reused(const password_type passwd_type, + const char *passwd, + int *is_reused) +{ + using namespace AuthPasswd; + + return try_catch([&] { + if (NULL == passwd || NULL == is_reused) { + LogError("Wrong input param"); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + + MessageBuffer send, recv; + + Serialization::Serialize(send, static_cast<int>(PasswordHdrs::HDR_CHK_PASSWD_REUSED)); + Serialization::Serialize(send, passwd_type); + Serialization::Serialize(send, std::string(passwd)); + + int retCode = sendToServer(SERVICE_SOCKET_PASSWD_SET, send.Pop(), recv); + if (AUTH_PASSWD_API_SUCCESS != retCode) { + LogDebug("Error in sendToServer. Error code: " << retCode); + return retCode; + } + + Deserialization::Deserialize(recv, retCode); + + if (AUTH_PASSWD_API_SUCCESS == retCode) { + Deserialization::Deserialize(recv, *is_reused); + } + + return retCode; + }); +} + +AUTH_PASSWD_API +int auth_passwd_set_passwd(const password_type passwd_type, + const char *cur_passwd, + const char *new_passwd) +{ + using namespace AuthPasswd; + + return try_catch([&] { + if (!cur_passwd) { + cur_passwd = NO_PASSWORD; + } + + if (isPasswordIncorrect(new_passwd) || strlen(cur_passwd) > MAX_PASSWORD_LEN) { + LogError("Wrong input param."); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + + if (!new_passwd) { + new_passwd = NO_PASSWORD; + } + + MessageBuffer send, recv; + + Serialization::Serialize(send, static_cast<int>(PasswordHdrs::HDR_SET_PASSWD)); + Serialization::Serialize(send, passwd_type); + Serialization::Serialize(send, std::string(cur_passwd)); + Serialization::Serialize(send, std::string(new_passwd)); + + int retCode = sendToServer(SERVICE_SOCKET_PASSWD_SET, send.Pop(), recv); + if (AUTH_PASSWD_API_SUCCESS != retCode) { + LogError("Error in sendToServer. Error code: " << retCode); + return retCode; + } + + Deserialization::Deserialize(recv, retCode); + + return retCode; + }); +} + +AUTH_PASSWD_API +int auth_passwd_set_passwd_recovery(const char *cur_recovery_passwd, + const char *new_normal_passwd) +{ + using namespace AuthPasswd; + + return try_catch([&] { + if (!new_normal_passwd || isPasswordIncorrect(new_normal_passwd) || + !cur_recovery_passwd || isPasswordIncorrect(cur_recovery_passwd)) { + + LogError("Wrong input param."); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + + MessageBuffer send, recv; + + Serialization::Serialize(send, static_cast<int>(PasswordHdrs::HDR_SET_PASSWD_RECOVERY)); + Serialization::Serialize(send, std::string(cur_recovery_passwd)); + Serialization::Serialize(send, std::string(new_normal_passwd)); + + int retCode = sendToServer(SERVICE_SOCKET_PASSWD_SET, send.Pop(), recv); + if (AUTH_PASSWD_API_SUCCESS != retCode) { + LogError("Error in sendToServer. Error code: " << retCode); + return retCode; + } + + Deserialization::Deserialize(recv, retCode); + + return retCode; + }); +} diff --git a/src/client/include/client-common.h b/src/client/include/client-common.h new file mode 100644 index 0000000..6d24c51 --- /dev/null +++ b/src/client/include/client-common.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file client-common.h + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + * @brief This file constains implementation of common types + * used in authentication password. + */ + +#ifndef _AUTH_PASSWD_CLIENT_ +#define _AUTH_PASSWD_CLIENT_ + +#include <unistd.h> + +#include <vector> +#include <functional> + +#include <message-buffer.h> + +#define AUTH_PASSWD_API __attribute__((visibility("default"))) + +extern "C" { + struct msghdr; +} + +namespace AuthPasswd { + +typedef std::vector<unsigned char> RawBuffer; + +int sendToServerWithFd(int fd, const RawBuffer &send, MessageBuffer &recv); + +int sendToServer(char const * const interface, const RawBuffer &send, MessageBuffer &recv); + +/* + * sendToServerAncData is special case when we want to receive file descriptor + * passed by Authentication Server on behalf of calling process. We can't get it with + * MessageBuffer. + * + * This function should be called _ONLY_ in this particular case. + * + */ +int sendToServerAncData(char const * const interface, const RawBuffer &send, struct msghdr &hdr); + +/* + * Decorator function that performs frequently repeated exception handling in + * SS client API functions. Accepts lambda expression as an argument. + */ +int try_catch(const std::function<int()>& func); + + +class SockRAII { +public: + SockRAII() + : m_sock(-1) + {} + + ~SockRAII() { + if (m_sock > -1 ) + close(m_sock); + } + + int Connect(char const * const interface); + + int Get() const { + return m_sock; + } + +private: + int m_sock; +}; +} // namespace AuthPasswd + +#endif // _AUTH_PASSWD_CLIENT_ diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt new file mode 100644 index 0000000..bec6f53 --- /dev/null +++ b/src/common/CMakeLists.txt @@ -0,0 +1,57 @@ +PKG_CHECK_MODULES(COMMON_DEP + dlog + libsmack + REQUIRED + ) + +SET(COMMON_SOURCES + ${COMMON_PATH}/error-description.cpp + ${COMMON_PATH}/protocols.cpp + ${COMMON_PATH}/message-buffer.cpp + ${COMMON_PATH}/smack-check.cpp + ${COMMON_PATH}/user-check.cpp + ${DPL_PATH}/log/src/abstract_log_provider.cpp + ${DPL_PATH}/log/src/dlog_log_provider.cpp + ${DPL_PATH}/log/src/log.cpp + ${DPL_PATH}/log/src/old_style_log_provider.cpp + ${DPL_PATH}/core/src/assert.cpp + ${DPL_PATH}/core/src/binary_queue.cpp + ${DPL_PATH}/core/src/colors.cpp + ${DPL_PATH}/core/src/exception.cpp + ${DPL_PATH}/core/src/noncopyable.cpp + ${DPL_PATH}/core/src/serialization.cpp + ${DPL_PATH}/core/src/singleton.cpp + ) + +SET_SOURCE_FILES_PROPERTIES( + ${COMMON_SOURCES} + PROPERTIES + COMPILE_FLAGS "-fvisibility=default" + ) + +INCLUDE_DIRECTORIES(SYSTEM + ${COMMON_DEP_INCLUDE_DIRS} + ) + +INCLUDE_DIRECTORIES( + ${COMMON_PATH}/include + ${PLUGIN_PATH}/include + ${DPL_PATH}/core/include + ${DPL_PATH}/log/include + ) + +ADD_LIBRARY(${TARGET_COMMON} SHARED ${COMMON_SOURCES}) + +SET_TARGET_PROPERTIES( + ${TARGET_COMMON} + PROPERTIES + COMPILE_FLAGS "-D_GNU_SOURCE -fPIC" + SOVERSION 1.0.0 + VERSION 1.0.0 + ) + +TARGET_LINK_LIBRARIES(${TARGET_COMMON} + ${COMMON_DEP_LIBRARIES} + ) + +INSTALL(TARGETS ${TARGET_COMMON} DESTINATION lib) diff --git a/src/common/error-description.cpp b/src/common/error-description.cpp new file mode 100644 index 0000000..62f7e55 --- /dev/null +++ b/src/common/error-description.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2000 - 2016 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 error-description.cpp + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + * @brief Implementatin of errorToString function. + */ +#include <string.h> + +#include <error-description.h> + +#define MAX_BUF 256 + +namespace AuthPasswd { + +std::string errnoToString(int err) { + char buffer[MAX_BUF] = {}; + +#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE + if (0 == strerror_r(err, buffer, MAX_BUF)) + return std::string(buffer); +#else + char *result = strerror_r(err, buffer, MAX_BUF); + if (result) + return std::string(result); +#endif + return std::string(); +} + +} // namespace AuthPasswd diff --git a/src/common/include/connection-info.h b/src/common/include/connection-info.h new file mode 100644 index 0000000..2d88ae1 --- /dev/null +++ b/src/common/include/connection-info.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file connection-info.h + * @author Lukasz Kostyra (l.kostyra@partner.samsung.com) + * @version 1.0 + * @brief Definition of ConnectionInfo structure and ConnectionInfoMap type. + */ + +#ifndef _CONNECTION_INFO_H_ +#define _CONNECTION_INFO_H_ + +#include <map> +#include <generic-socket-manager.h> +#include <message-buffer.h> + +namespace AuthPasswd +{ + struct ConnectionInfo { + InterfaceID interfaceID; + MessageBuffer buffer; + }; + + typedef std::map<int, ConnectionInfo> ConnectionInfoMap; +} //namespace AuthPasswd + +#endif //_CONNECTION_INFO_H_ diff --git a/src/common/include/error-description.h b/src/common/include/error-description.h new file mode 100644 index 0000000..f4e7613 --- /dev/null +++ b/src/common/include/error-description.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2000 - 2016 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 error-description.h + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + * @brief Implementatin of errorToString function. + */ +#ifndef _AUTH_PASSWD_ERROR_DESCRIPTION_ +#define _AUTH_PASSWD_ERROR_DESCRIPTION_ + +#include <string> + +namespace AuthPasswd { + +std::string errnoToString(int err); + +} // namespace AuthPasswd + +#endif // _AUTH_PASSWD_ERROR_DESCRIPTION_ diff --git a/src/common/include/message-buffer.h b/src/common/include/message-buffer.h new file mode 100644 index 0000000..0707017 --- /dev/null +++ b/src/common/include/message-buffer.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file secket-buffer.h + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + * @brief Implementatin of MessageBuffer. + */ + +#ifndef _AUTH_PASSWD_SOCKET_BUFFER_ +#define _AUTH_PASSWD_SOCKET_BUFFER_ + +#include <vector> + +#include <dpl/binary_queue.h> +#include <dpl/exception.h> +#include <dpl/serialization.h> + +namespace AuthPasswd { + +typedef std::vector<unsigned char> RawBuffer; + +class MessageBuffer : public AuthPasswd::IStream { +public: + class Exception + { + public: + DECLARE_EXCEPTION_TYPE(AuthPasswd::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, OutOfData) + }; + + MessageBuffer() + : m_bytesLeft(0) + {} + + void Push(const RawBuffer &data); + + RawBuffer Pop(); + + bool Ready(); + + virtual void Read(size_t num, void *bytes); + + virtual void Write(size_t num, const void *bytes); + +protected: + + inline void CountBytesLeft() { + if (m_bytesLeft > 0) + return; // we already counted m_bytesLeft nothing to do + + if (m_buffer.Size() < sizeof(size_t)) + return; // we cannot count m_bytesLeft because buffer is too small + + m_buffer.FlattenConsume(&m_bytesLeft, sizeof(size_t)); + } + + size_t m_bytesLeft; + AuthPasswd::BinaryQueue m_buffer; +}; + +} // namespace AuthPasswd + +#endif // _AUTH_PASSWD_SOCKET_BUFFER_ diff --git a/src/common/include/policy.h b/src/common/include/policy.h new file mode 100644 index 0000000..60e7fbf --- /dev/null +++ b/src/common/include/policy.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file policy.h + * @author Jooseong Lee (jooseong.lee@samsung.com) + * @version 1.0 + * @brief Implementatin of MessageBuffer. + */ + +#ifndef _AUTH_PASSWD_POLICY_H_ +#define _AUTH_PASSWD_POLICY_H_ + +#include <auth-passwd-policy-types.h> + +struct auth_password_policy { + + uid_t uid; + unsigned int maxAttempts; + unsigned int validPeriod; + unsigned int historySize; + unsigned int minLength; + password_quality_type qualityType; +}; + +#endif // _AUTH_PASSWD_POLICY_H_ diff --git a/src/common/include/protocols.h b/src/common/include/protocols.h new file mode 100644 index 0000000..047a962 --- /dev/null +++ b/src/common/include/protocols.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file protocols.h + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @author Jooseong Lee (jooseong.lee@samsung.com) + * @version 1.0 + * @brief This file contains list of all protocols suported by authentication password. + */ + +#ifndef _AUTH_PASSWD_PROTOCOLS_ +#define _AUTH_PASSWD_PROTOCOLS_ + +#include <cstddef> +#include <time.h> +#include <sys/types.h> + +namespace AuthPasswd { + +extern char const * const SERVICE_SOCKET_PASSWD_CHECK; +extern char const * const SERVICE_SOCKET_PASSWD_SET; +extern char const * const SERVICE_SOCKET_PASSWD_RESET; +extern char const * const SERVICE_SOCKET_PASSWD_POLICY; + +enum class PasswordHdrs +{ + HDR_CHK_PASSWD, + HDR_CHK_PASSWD_STATE, + HDR_CHK_PASSWD_REUSED, + HDR_SET_PASSWD, + HDR_SET_PASSWD_RECOVERY, + HDR_RST_PASSWD, + HDR_SET_PASSWD_POLICY +}; + +extern const size_t MAX_PASSWORD_LEN; +extern const unsigned int MAX_PASSWORD_HISTORY; +extern const unsigned int PASSWORD_INFINITE_EXPIRATION_DAYS; +extern const unsigned int PASSWORD_INFINITE_ATTEMPT_COUNT; +extern const unsigned int PASSWORD_API_NO_EXPIRATION; + +} // namespace AuthPasswd + +#endif // _AUTH_PASSWD_PROTOCOLS_ + diff --git a/src/common/include/smack-check.h b/src/common/include/smack-check.h new file mode 100644 index 0000000..43fc4a6 --- /dev/null +++ b/src/common/include/smack-check.h @@ -0,0 +1,42 @@ +/* + * Authentication password + * + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 AuthPasswd { + +/* + * 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 AuthPasswd + +#endif // _SMACK_CHECK_H_ diff --git a/src/common/include/user-check.h b/src/common/include/user-check.h new file mode 100644 index 0000000..a16a7b8 --- /dev/null +++ b/src/common/include/user-check.h @@ -0,0 +1,29 @@ +/* + * Authentication password + * + * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ + +#include <sys/socket.h> +#include <sys/un.h> + +namespace AuthPasswd { + +int socket_get_user(int sockfd, unsigned int &user); + +} // namespace AuthPasswd + diff --git a/src/common/message-buffer.cpp b/src/common/message-buffer.cpp new file mode 100644 index 0000000..80bdd96 --- /dev/null +++ b/src/common/message-buffer.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file message-buffer.cpp + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + * @brief Implementation of MessageBuffer. + */ + +#include <message-buffer.h> + +#include <dpl/log/log.h> + +namespace AuthPasswd { + +void MessageBuffer::Push(const RawBuffer &data) { + m_buffer.AppendCopy(&data[0], data.size()); +} + +RawBuffer MessageBuffer::Pop() { + size_t size = m_buffer.Size(); + RawBuffer buffer; + buffer.resize(size + sizeof(size_t)); + memcpy(&buffer[0], &size, sizeof(size_t)); + m_buffer.FlattenConsume(&buffer[sizeof(size_t)], size); + return buffer; +} + +bool MessageBuffer::Ready() { + CountBytesLeft(); + if (m_bytesLeft == 0) + return false; + if (m_bytesLeft > m_buffer.Size()) + return false; + return true; +} + +void MessageBuffer::Read(size_t num, void *bytes) { + CountBytesLeft(); + if (num > m_bytesLeft) { + LogDebug("Protocol broken. OutOfData. Asked for: " << num << " Ready: " << m_bytesLeft << " Buffer.size(): " << m_buffer.Size()); + Throw(Exception::OutOfData); + } + + m_buffer.FlattenConsume(bytes, num); + m_bytesLeft -= num; +} + +void MessageBuffer::Write(size_t num, const void *bytes) { + m_buffer.AppendCopy(bytes, num); +} + +} // namespace AuthPasswd + diff --git a/src/common/protocols.cpp b/src/common/protocols.cpp new file mode 100644 index 0000000..a8bd92e --- /dev/null +++ b/src/common/protocols.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file protocols.cpp + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @author Jooseong Lee (jooseong.lee@samsung.com) + * @version 1.0 + * @brief List of all protocols supported by authentication password. + */ + +#include <protocols.h> +#include <cstddef> + +namespace AuthPasswd { + +char const * const SERVICE_SOCKET_PASSWD_CHECK = + "/run/.authentication-server-api-passwd-check.sock"; +char const * const SERVICE_SOCKET_PASSWD_SET = + "/run/.authentication-server-api-passwd-set.sock"; +char const * const SERVICE_SOCKET_PASSWD_RESET = + "/run/.authentication-server-api-passwd-reset.sock"; +char const * const SERVICE_SOCKET_PASSWD_POLICY = + "/run/.authentication-server-api-passwd-policy.sock"; + +const size_t MAX_PASSWORD_LEN = 32; +const unsigned int MAX_PASSWORD_HISTORY = 50; +const unsigned int PASSWORD_INFINITE_EXPIRATION_DAYS = 0; +const unsigned int PASSWORD_INFINITE_ATTEMPT_COUNT = 0; +const unsigned int PASSWORD_API_NO_EXPIRATION = 0xFFFFFFFF; + +} // namespace AuthPasswd + diff --git a/src/common/smack-check.cpp b/src/common/smack-check.cpp new file mode 100644 index 0000000..8b1e414 --- /dev/null +++ b/src/common/smack-check.cpp @@ -0,0 +1,34 @@ +#include <smack-check.h> + +#include <stdlib.h> +#include <sys/smack.h> + +#include <dpl/log/log.h> + +namespace AuthPasswd { + +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 AuthPasswd diff --git a/src/common/user-check.cpp b/src/common/user-check.cpp new file mode 100644 index 0000000..0776b7c --- /dev/null +++ b/src/common/user-check.cpp @@ -0,0 +1,19 @@ +#include <user-check.h> +#include <dpl/log/log.h> + +namespace AuthPasswd { + +int socket_get_user(int sockfd, unsigned int &user) +{ + struct ucred cr; + socklen_t len = sizeof(struct ucred); + if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cr, &len)) + { + LogError("getsockopt() failed"); + return 1; + } + user = cr.uid; + return 0; +} + +} // namespace AuthPasswd diff --git a/src/dpl/core/include/dpl/assert.h b/src/dpl/core/include/dpl/assert.h new file mode 100644 index 0000000..adcd289 --- /dev/null +++ b/src/dpl/core/include/dpl/assert.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2011 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 assert.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of assert + */ +#ifndef AUTH_PASSWD_ASSERT_H +#define AUTH_PASSWD_ASSERT_H + +#include <dpl/noreturn.h> + +namespace AuthPasswd { +// Assertion handler procedure +// Do not call directly +// Always use Assert macro +AUTHPASSWD_NORETURN void AssertProc(const char *condition, + const char *file, + int line, + const char *function); +} // namespace AuthPasswd + +#define Assert(Condition) do { if (!(Condition)) { AuthPasswd::AssertProc(#Condition, \ + __FILE__, \ + __LINE__, \ + __FUNCTION__); \ + } } while (0) + +#endif // AUTH_PASSWD_ASSERT_H diff --git a/src/dpl/core/include/dpl/binary_queue.h b/src/dpl/core/include/dpl/binary_queue.h new file mode 100644 index 0000000..9f29570 --- /dev/null +++ b/src/dpl/core/include/dpl/binary_queue.h @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2011 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 binary_queue.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief This file is the header file of binary queue + */ +#ifndef AUTH_PASSWD_BINARY_QUEUE_H +#define AUTH_PASSWD_BINARY_QUEUE_H + +//#include <dpl/abstract_input_output.h> +#include <dpl/exception.h> +#include <dpl/noncopyable.h> +#include <memory> +#include <list> + +namespace AuthPasswd { +/** + * Binary queue auto pointer + */ +class BinaryQueue; +typedef std::auto_ptr<BinaryQueue> BinaryQueueAutoPtr; + +/** + * Binary stream implemented as constant size bucket list + * + * @todo Add optimized implementation for FlattenConsume + */ +class BinaryQueue +// : public AbstractInputOutput +{ + public: + class Exception + { + public: + DECLARE_EXCEPTION_TYPE(AuthPasswd::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, OutOfData) + }; + + typedef void (*BufferDeleter)(const void *buffer, size_t bufferSize, + void *userParam); + static void BufferDeleterFree(const void *buffer, + size_t bufferSize, + void *userParam); + + class BucketVisitor + { + public: + /** + * Destructor + */ + virtual ~BucketVisitor(); + + /** + * Visit bucket + * + * @return none + * @param[in] buffer Constant pointer to bucket data buffer + * @param[in] bufferSize Number of bytes in bucket + */ + virtual void OnVisitBucket(const void *buffer, size_t bufferSize) = 0; + }; + + private: + struct Bucket : + private Noncopyable + { + const void *buffer; + const void *ptr; + size_t size; + size_t left; + + BufferDeleter deleter; + void *param; + + Bucket(const void *buffer, + size_t bufferSize, + BufferDeleter deleter, + void *userParam); + virtual ~Bucket(); + }; + + typedef std::list<Bucket *> BucketList; + BucketList m_buckets; + size_t m_size; + + static void DeleteBucket(Bucket *bucket); + + class BucketVisitorCall + { + private: + BucketVisitor *m_visitor; + + public: + BucketVisitorCall(BucketVisitor *visitor); + virtual ~BucketVisitorCall(); + + void operator()(Bucket *bucket) const; + }; + + public: + /** + * Construct empty binary queue + */ + BinaryQueue(); + + /** + * Construct binary queue via bare copy of other binary queue + * + * @param[in] other Other binary queue to copy from + * @warning One cannot assume that bucket structure is preserved during copy + */ + BinaryQueue(const BinaryQueue &other); + + /** + * Destructor + */ + virtual ~BinaryQueue(); + + /** + * Construct binary queue via bare copy of other binary queue + * + * @param[in] other Other binary queue to copy from + * @warning One cannot assume that bucket structure is preserved during copy + */ + const BinaryQueue &operator=(const BinaryQueue &other); + + /** + * Append copy of @a bufferSize bytes from memory pointed by @a buffer + * to the end of binary queue. Uses default deleter based on free. + * + * @return none + * @param[in] buffer Pointer to buffer to copy data from + * @param[in] bufferSize Number of bytes to copy + * @exception std::bad_alloc Cannot allocate memory to hold additional data + * @see BinaryQueue::BufferDeleterFree + */ + void AppendCopy(const void *buffer, size_t bufferSize); + + /** + * Append @a bufferSize bytes from memory pointed by @a buffer + * to the end of binary queue. Uses custom provided deleter. + * Responsibility for deleting provided buffer is transfered to BinaryQueue. + * + * @return none + * @param[in] buffer Pointer to data buffer + * @param[in] bufferSize Number of bytes available in buffer + * @param[in] deleter Pointer to deleter procedure used to free provided + * buffer + * @param[in] userParam User parameter passed to deleter routine + * @exception std::bad_alloc Cannot allocate memory to hold additional data + */ + void AppendUnmanaged( + const void *buffer, + size_t bufferSize, + BufferDeleter deleter = + &BinaryQueue::BufferDeleterFree, + void *userParam = NULL); + + /** + * Append copy of other binary queue to the end of this binary queue + * + * @return none + * @param[in] other Constant reference to other binary queue to copy data + * from + * @exception std::bad_alloc Cannot allocate memory to hold additional data + * @warning One cannot assume that bucket structure is preserved during copy + */ + void AppendCopyFrom(const BinaryQueue &other); + + /** + * Move bytes from other binary queue to the end of this binary queue. + * This also removes all bytes from other binary queue. + * This method is designed to be as fast as possible (only pointer swaps) + * and is suggested over making copies of binary queues. + * Bucket structure is preserved after operation. + * + * @return none + * @param[in] other Reference to other binary queue to move data from + * @exception std::bad_alloc Cannot allocate memory to hold additional data + */ + void AppendMoveFrom(BinaryQueue &other); + + /** + * Append copy of binary queue to the end of other binary queue + * + * @return none + * @param[in] other Constant reference to other binary queue to copy data to + * @exception std::bad_alloc Cannot allocate memory to hold additional data + * @warning One cannot assume that bucket structure is preserved during copy + */ + void AppendCopyTo(BinaryQueue &other) const; + + /** + * Move bytes from binary queue to the end of other binary queue. + * This also removes all bytes from binary queue. + * This method is designed to be as fast as possible (only pointer swaps) + * and is suggested over making copies of binary queues. + * Bucket structure is preserved after operation. + * + * @return none + * @param[in] other Reference to other binary queue to move data to + * @exception std::bad_alloc Cannot allocate memory to hold additional data + */ + void AppendMoveTo(BinaryQueue &other); + + /** + * Retrieve total size of all data contained in binary queue + * + * @return Number of bytes in binary queue + */ + size_t Size() const; + + /** + * Remove all data from binary queue + * + * @return none + */ + void Clear(); + + /** + * Check if binary queue is empty + * + * @return true if binary queue is empty, false otherwise + */ + bool Empty() const; + + /** + * Remove @a size bytes from beginning of binary queue + * + * @return none + * @param[in] size Number of bytes to remove + * @exception BinaryQueue::Exception::OutOfData Number of bytes is larger + * than available bytes in binary queue + */ + void Consume(size_t size); + + /** + * Retrieve @a bufferSize bytes from beginning of binary queue and copy them + * to user supplied buffer + * + * @return none + * @param[in] buffer Pointer to user buffer to receive bytes + * @param[in] bufferSize Size of user buffer pointed by @a buffer + * @exception BinaryQueue::Exception::OutOfData Number of bytes to flatten + * is larger than available bytes in binary queue + */ + void Flatten(void *buffer, size_t bufferSize) const; + + /** + * Retrieve @a bufferSize bytes from beginning of binary queue, copy them + * to user supplied buffer, and remove from binary queue + * + * @return none + * @param[in] buffer Pointer to user buffer to receive bytes + * @param[in] bufferSize Size of user buffer pointed by @a buffer + * @exception BinaryQueue::Exception::OutOfData Number of bytes to flatten + * is larger than available bytes in binary queue + */ + void FlattenConsume(void *buffer, size_t bufferSize); + + /** + * Visit each buffer with data using visitor object + * + * @return none + * @param[in] visitor Pointer to bucket visitor + * @see BinaryQueue::BucketVisitor + */ + void VisitBuckets(BucketVisitor *visitor) const; + + /** + * IAbstractInput interface + */ + virtual BinaryQueueAutoPtr Read(size_t size); + + /** + * IAbstractOutput interface + */ + virtual size_t Write(const BinaryQueue &buffer, size_t bufferSize); +}; + +} // namespace AuthPasswd + +#endif // AUTH_PASSWD_BINARY_QUEUE_H diff --git a/src/dpl/core/include/dpl/colors.h b/src/dpl/core/include/dpl/colors.h new file mode 100644 index 0000000..400647e --- /dev/null +++ b/src/dpl/core/include/dpl/colors.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2011 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 colors.h + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 1.0 + * @brief Some constants with definition of colors for Console + * and html output + */ + +#ifndef AUTH_PASSWD_COLORS_H +#define AUTH_PASSWD_COLORS_H + +namespace AuthPasswd { +namespace Colors { +namespace Text { +extern const char* BOLD_GREEN_BEGIN; +extern const char* BOLD_GREEN_END; +extern const char* PURPLE_BEGIN; +extern const char* PURPLE_END; +extern const char* RED_BEGIN; +extern const char* RED_END; +extern const char* GREEN_BEGIN; +extern const char* GREEN_END; +extern const char* CYAN_BEGIN; +extern const char* CYAN_END; +extern const char* BOLD_RED_BEGIN; +extern const char* BOLD_RED_END; +extern const char* BOLD_YELLOW_BEGIN; +extern const char* BOLD_YELLOW_END; +extern const char* BOLD_GOLD_BEGIN; +extern const char* BOLD_GOLD_END; +extern const char* BOLD_WHITE_BEGIN; +extern const char* BOLD_WHITE_END; +} //namespace Text + +namespace Html { +extern const char* BOLD_GREEN_BEGIN; +extern const char* BOLD_GREEN_END; +extern const char* PURPLE_BEGIN; +extern const char* PURPLE_END; +extern const char* RED_BEGIN; +extern const char* RED_END; +extern const char* GREEN_BEGIN; +extern const char* GREEN_END; +extern const char* CYAN_BEGIN; +extern const char* CYAN_END; +extern const char* BOLD_RED_BEGIN; +extern const char* BOLD_RED_END; +extern const char* BOLD_YELLOW_BEGIN; +extern const char* BOLD_YELLOW_END; +extern const char* BOLD_GOLD_BEGIN; +extern const char* BOLD_GOLD_END; +extern const char* BOLD_WHITE_BEGIN; +extern const char* BOLD_WHITE_END; +} //namespace Html +} //namespace Colors +} //namespace AuthPasswd + +#endif /* AUTH_PASSWD_COLORS_H */ diff --git a/src/dpl/core/include/dpl/exception.h b/src/dpl/core/include/dpl/exception.h new file mode 100644 index 0000000..2d66d62 --- /dev/null +++ b/src/dpl/core/include/dpl/exception.h @@ -0,0 +1,385 @@ +/* + * Copyright (c) 2011 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 exception.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief Header file for base exception + */ +#ifndef AUTH_PASSWD_EXCEPTION_H +#define AUTH_PASSWD_EXCEPTION_H + +#include <string> +#include <cstring> +#include <cstdio> +#include <exception> +#include <cstdlib> +#include <sstream> + +namespace AuthPasswd { +void LogUnhandledException(const std::string &str); +void LogUnhandledException(const std::string &str, + const char *filename, + int line, + const char *function); +} + +namespace AuthPasswd { +class Exception +{ + private: + static unsigned int m_exceptionCount; + static Exception* m_lastException; + static void (*m_terminateHandler)(); + + static void AddRef(Exception* exception) + { + if (!m_exceptionCount) { + m_terminateHandler = std::set_terminate(&TerminateHandler); + } + + ++m_exceptionCount; + m_lastException = exception; + } + + static void UnRef(Exception* e) + { + if (m_lastException == e) { + m_lastException = NULL; + } + + --m_exceptionCount; + + if (!m_exceptionCount) { + std::set_terminate(m_terminateHandler); + m_terminateHandler = NULL; + } + } + + static void TerminateHandler() + { + if (m_lastException != NULL) { + DisplayKnownException(*m_lastException); + abort(); + } else { + DisplayUnknownException(); + abort(); + } + } + + Exception *m_reason; + std::string m_path; + std::string m_function; + int m_line; + + protected: + std::string m_message; + std::string m_className; + + public: + static std::string KnownExceptionToString(const Exception &e) + { + std::ostringstream message; + message << + "\033[1;5;31m\n=== Unhandled AuthPasswd exception occurred ===\033[m\n\n"; + message << "\033[1;33mException trace:\033[m\n\n"; + message << e.DumpToString(); + message << "\033[1;31m\n=== Will now abort ===\033[m\n"; + + return message.str(); + } + + static std::string UnknownExceptionToString() + { + std::ostringstream message; + message << + "\033[1;5;31m\n=== Unhandled non-AuthPasswd exception occurred ===\033[m\n\n"; + message << "\033[1;31m\n=== Will now abort ===\033[m\n"; + + return message.str(); + } + + static void DisplayKnownException(const Exception& e) + { + LogUnhandledException(KnownExceptionToString(e).c_str()); + } + + static void DisplayUnknownException() + { + LogUnhandledException(UnknownExceptionToString().c_str()); + } + + Exception(const Exception &other) + { + // Deep copy + if (other.m_reason != NULL) { + m_reason = new Exception(*other.m_reason); + } else { + m_reason = NULL; + } + + m_message = other.m_message; + m_path = other.m_path; + m_function = other.m_function; + m_line = other.m_line; + + m_className = other.m_className; + + AddRef(this); + } + + const Exception &operator =(const Exception &other) + { + if (this == &other) { + return *this; + } + + // Deep copy + if (other.m_reason != NULL) { + m_reason = new Exception(*other.m_reason); + } else { + m_reason = NULL; + } + + m_message = other.m_message; + m_path = other.m_path; + m_function = other.m_function; + m_line = other.m_line; + + m_className = other.m_className; + + AddRef(this); + + return *this; + } + + Exception(const char *path, + const char *function, + int line, + const std::string &message) : + m_reason(NULL), + m_path(path), + m_function(function), + m_line(line), + m_message(message) + { + AddRef(this); + } + + Exception(const char *path, + const char *function, + int line, + const Exception &reason, + const std::string &message) : + m_reason(new Exception(reason)), + m_path(path), + m_function(function), + m_line(line), + m_message(message) + { + AddRef(this); + } + + virtual ~Exception() throw() + { + if (m_reason != NULL) { + delete m_reason; + m_reason = NULL; + } + + UnRef(this); + } + + void Dump() const + { + // Show reason first + if (m_reason != NULL) { + m_reason->Dump(); + } + + // Afterward, dump exception + const char *file = strchr(m_path.c_str(), '/'); + + if (file == NULL) { + file = m_path.c_str(); + } else { + ++file; + } + + printf("\033[0;36m[%s:%i]\033[m %s() \033[4;35m%s\033[m: %s\033[m\n", + file, m_line, + m_function.c_str(), + m_className.c_str(), + m_message.empty() ? "<EMPTY>" : m_message.c_str()); + } + + std::string DumpToString() const + { + std::string ret; + if (m_reason != NULL) { + ret = m_reason->DumpToString(); + } + + const char *file = strchr(m_path.c_str(), '/'); + + if (file == NULL) { + file = m_path.c_str(); + } else { + ++file; + } + + char buf[1024]; + snprintf(buf, + sizeof(buf), + "\033[0;36m[%s:%i]\033[m %s() \033[4;35m%s\033[m: %s\033[m\n", + file, + m_line, + m_function.c_str(), + m_className.c_str(), + m_message.empty() ? "<EMPTY>" : m_message.c_str()); + + buf[sizeof(buf) - 1] = '\n'; + ret += buf; + + return ret; + } + + Exception *GetReason() const + { + return m_reason; + } + + std::string GetPath() const + { + return m_path; + } + + std::string GetFunction() const + { + return m_function; + } + + int GetLine() const + { + return m_line; + } + + std::string GetMessage() const + { + return m_message; + } + + std::string GetClassName() const + { + return m_className; + } +}; +} // namespace AuthPasswd + +#define Try try + +#define Throw(ClassName) \ + throw ClassName(__FILE__, __FUNCTION__, __LINE__) + +#define ThrowMsg(ClassName, Message) \ + do \ + { \ + std::ostringstream dplLoggingStream; \ + dplLoggingStream << Message; \ + throw ClassName(__FILE__, __FUNCTION__, __LINE__, dplLoggingStream.str()); \ + } while (0) + +#define ReThrow(ClassName) \ + throw ClassName(__FILE__, __FUNCTION__, __LINE__, _rethrown_exception) + +#define ReThrowMsg(ClassName, Message) \ + throw ClassName(__FILE__, \ + __FUNCTION__, \ + __LINE__, \ + _rethrown_exception, \ + Message) + +#define Catch(ClassName) \ + catch (const ClassName &_rethrown_exception) + +#define DECLARE_EXCEPTION_TYPE(BaseClass, Class) \ + class Class : \ + public BaseClass \ + { \ + public: \ + Class(const char *path, \ + const char *function, \ + int line, \ + const std::string & message = std::string()) : \ + BaseClass(path, function, line, message) \ + { \ + BaseClass::m_className = #Class; \ + } \ + \ + Class(const char *path, \ + const char *function, \ + int line, \ + const AuthPasswd::Exception & reason, \ + const std::string & message = std::string()) : \ + BaseClass(path, function, line, reason, message) \ + { \ + BaseClass::m_className = #Class; \ + } \ + }; + +#define UNHANDLED_EXCEPTION_HANDLER_BEGIN try + +#define UNHANDLED_EXCEPTION_HANDLER_END \ + catch (const AuthPasswd::Exception &exception) \ + { \ + std::ostringstream msg; \ + msg << AuthPasswd::Exception::KnownExceptionToString(exception); \ + AuthPasswd::LogUnhandledException(msg.str(), __FILE__, __LINE__, __FUNCTION__); \ + abort(); \ + } \ + catch (std::exception& e) \ + { \ + std::ostringstream msg; \ + msg << e.what(); \ + msg << "\n"; \ + msg << AuthPasswd::Exception::UnknownExceptionToString(); \ + AuthPasswd::LogUnhandledException(msg.str(), __FILE__, __LINE__, __FUNCTION__); \ + abort(); \ + } \ + catch (...) \ + { \ + std::ostringstream msg; \ + msg << AuthPasswd::Exception::UnknownExceptionToString(); \ + AuthPasswd::LogUnhandledException(msg.str(), __FILE__, __LINE__, __FUNCTION__); \ + abort(); \ + } + +namespace AuthPasswd { +namespace CommonException { +/** + * Internal exception definitions + * + * These should normally not happen. + * Usually, exception trace with internal error includes + * important messages. + */ +DECLARE_EXCEPTION_TYPE(Exception, InternalError) ///< Unexpected error from + // underlying libraries or + // kernel +} +} + +#endif // AUTH_PASSWD_EXCEPTION_H diff --git a/src/dpl/core/include/dpl/fstream_accessors.h b/src/dpl/core/include/dpl/fstream_accessors.h new file mode 100644 index 0000000..ea692bd --- /dev/null +++ b/src/dpl/core/include/dpl/fstream_accessors.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + * + * @file fstream-helper.h + * @author Marek Smolinski (m.smolinski@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of fstream-helper + * + */ + +#ifndef AUTH_PASSWD_FSTREAM_ACCESSORS_H +#define AUTH_PASSWD_FSTREAM_ACCESSORS_H + +namespace DPL { + +/* + * Bypass lack of public member function to get file + * descriptor from fstream objects in std + * This feature is needed for flushing data from kernel space buffer to + * physical device [fsync(int fd) - syscall] on opened fstream object +*/ + +template<typename T> +class FstreamAccessors : T::__filebuf_type { + typedef FstreamAccessors<T> MyType; +public: + static int GetFd(T &strm) { + return static_cast<MyType *>(strm.rdbuf())->_M_file.fd(); + } +}; + +} // namespace DPL + +#endif // AUTH_PASSWD_FSTREAM_ACCESSORS_H diff --git a/src/dpl/core/include/dpl/noncopyable.h b/src/dpl/core/include/dpl/noncopyable.h new file mode 100644 index 0000000..873f386 --- /dev/null +++ b/src/dpl/core/include/dpl/noncopyable.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011 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 noncopyable + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of noncopyable + */ +#ifndef AUTHPASSWD_NONCOPYABLE_H +#define AUTHPASSWD_NONCOPYABLE_H + +namespace AuthPasswd { +class Noncopyable +{ + private: + Noncopyable(const Noncopyable &); + const Noncopyable &operator=(const Noncopyable &); + + public: + Noncopyable(); + virtual ~Noncopyable(); +}; +} // namespace AuthPasswd + +#endif // AUTHPASSWD_NONCOPYABLE_H diff --git a/src/dpl/core/include/dpl/noreturn.h b/src/dpl/core/include/dpl/noreturn.h new file mode 100644 index 0000000..7da368f --- /dev/null +++ b/src/dpl/core/include/dpl/noreturn.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2011 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 noreturn.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of noreturn + */ +#ifndef AUTHPASSWD_NORETURN_H +#define AUTHPASSWD_NORETURN_H + +#define AUTHPASSWD_NORETURN __attribute__((__noreturn__)) + +#endif // AUTHPASSWD_NORETURN_H diff --git a/src/dpl/core/include/dpl/serialization.h b/src/dpl/core/include/dpl/serialization.h new file mode 100644 index 0000000..ab7a193 --- /dev/null +++ b/src/dpl/core/include/dpl/serialization.h @@ -0,0 +1,405 @@ +/* + * Copyright (c) 2011 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 serialization.h + * @author Tomasz Swierczek (t.swierczek@samsung.com) + * @version 1.0 + * @brief Interfaces and templates used for data serialization. + */ +#ifndef SERIALIZATION_H +#define SERIALIZATION_H + +#include <string> +#include <vector> +#include <list> +#include <map> +#include <memory> + +namespace AuthPasswd { +// Abstract data stream buffer +class IStream +{ + public: + virtual void Read(size_t num, void * bytes) = 0; + virtual void Write(size_t num, const void * bytes) = 0; + virtual ~IStream(){} +}; + +// Serializable interface +class ISerializable +{ + public: + /* ISerializable(){}; + * ISerializable(IStream&){}; */ + virtual void Serialize(IStream &) const = 0; + virtual ~ISerializable(){} +}; + +struct Serialization { + // serialization + // normal functions + + // ISerializable objects + static void Serialize(IStream& stream, const ISerializable& object) + { + object.Serialize(stream); + } + static void Serialize(IStream& stream, const ISerializable* const object) + { + object->Serialize(stream); + } + + // char + static void Serialize(IStream& stream, const char value) + { + stream.Write(sizeof(value), &value); + } + static void Serialize(IStream& stream, const char* const value) + { + stream.Write(sizeof(*value), value); + } + + // unsigned char + static void Serialize(IStream& stream, const unsigned char value) + { + stream.Write(sizeof(value), &value); + } + static void Serialize(IStream& stream, const unsigned char* const value) + { + stream.Write(sizeof(*value), value); + } + + // unsigned int + static void Serialize(IStream& stream, const unsigned value) + { + stream.Write(sizeof(value), &value); + } + static void Serialize(IStream& stream, const unsigned* const value) + { + stream.Write(sizeof(*value), value); + } + + // int + static void Serialize(IStream& stream, const int value) + { + stream.Write(sizeof(value), &value); + } + static void Serialize(IStream& stream, const int* const value) + { + stream.Write(sizeof(*value), value); + } + + // bool + static void Serialize(IStream& stream, const bool value) + { + stream.Write(sizeof(value), &value); + } + static void Serialize(IStream& stream, const bool* const value) + { + stream.Write(sizeof(*value), value); + } + + // time_t + static void Serialize(IStream& stream, const time_t value) + { + stream.Write(sizeof(value), &value); + } + static void Serialize(IStream& stream, const time_t* const value) + { + stream.Write(sizeof(*value), value); + } + + // std::string + static void Serialize(IStream& stream, const std::string& str) + { + int length = str.size(); + stream.Write(sizeof(length), &length); + stream.Write(length, str.c_str()); + } + static void Serialize(IStream& stream, const std::string* const str) + { + int length = str->size(); + stream.Write(sizeof(length), &length); + stream.Write(length, str->c_str()); + } + + // STL templates + + // std::list + template <typename T> + static void Serialize(IStream& stream, const std::list<T>& list) + { + int length = list.size(); + stream.Write(sizeof(length), &length); + for (typename std::list<T>::const_iterator list_iter = list.begin(); + list_iter != list.end(); list_iter++) + { + Serialize(stream, *list_iter); + } + } + template <typename T> + static void Serialize(IStream& stream, const std::list<T>* const list) + { + Serialize(stream, *list); + } + + // std::vector + template <typename T> + static void Serialize(IStream& stream, const std::vector<T>& vec) + { + int length = vec.size(); + stream.Write(sizeof(length), &length); + for (typename std::vector<T>::const_iterator vec_iter = vec.begin(); + vec_iter != vec.end(); vec_iter++) + { + Serialize(stream, *vec_iter); + } + } + template <typename T> + static void Serialize(IStream& stream, const std::vector<T>* const vec) + { + Serialize(stream, *vec); + } + + // std::pair + template <typename A, typename B> + static void Serialize(IStream& stream, const std::pair<A, B>& p) + { + Serialize(stream, p.first); + Serialize(stream, p.second); + } + template <typename A, typename B> + static void Serialize(IStream& stream, const std::pair<A, B>* const p) + { + Serialize(stream, *p); + } + + // std::map + template <typename K, typename T> + static void Serialize(IStream& stream, const std::map<K, T>& map) + { + int length = map.size(); + stream.Write(sizeof(length), &length); + typename std::map<K, T>::const_iterator it; + for (it = map.begin(); it != map.end(); ++it) { + Serialize(stream, (*it).first); + Serialize(stream, (*it).second); + } + } + template <typename K, typename T> + static void Serialize(IStream& stream, const std::map<K, T>* const map) + { + Serialize(stream, *map); + } + + // std::unique_ptr + template <typename T> + static void Serialize(IStream& stream, const std::unique_ptr<T>& p) + { + Serialize(stream, *p); + } + + // std::shared_ptr + template <typename T> + static void Serialize(IStream& stream, const std::shared_ptr<T>& p) + { + Serialize(stream, *p); + } +}; // struct Serialization + +struct Deserialization { + // deserialization + // normal functions + + // ISerializable objects + // T instead of ISerializable is needed to call proper constructor + template <typename T> + static void Deserialize(IStream& stream, T& object) + { + object = T(stream); + } + template <typename T> + static void Deserialize(IStream& stream, T*& object) + { + object = new T(stream); + } + + // char + static void Deserialize(IStream& stream, char& value) + { + stream.Read(sizeof(value), &value); + } + static void Deserialize(IStream& stream, char*& value) + { + value = new char; + stream.Read(sizeof(*value), value); + } + + // unsigned char + static void Deserialize(IStream& stream, unsigned char& value) + { + stream.Read(sizeof(value), &value); + } + static void Deserialize(IStream& stream, unsigned char*& value) + { + value = new unsigned char; + stream.Read(sizeof(*value), value); + } + + // unsigned int + static void Deserialize(IStream& stream, unsigned& value) + { + stream.Read(sizeof(value), &value); + } + static void Deserialize(IStream& stream, unsigned*& value) + { + value = new unsigned; + stream.Read(sizeof(*value), value); + } + + // int + static void Deserialize(IStream& stream, int& value) + { + stream.Read(sizeof(value), &value); + } + static void Deserialize(IStream& stream, int*& value) + { + value = new int; + stream.Read(sizeof(*value), value); + } + + // bool + static void Deserialize(IStream& stream, bool& value) + { + stream.Read(sizeof(value), &value); + } + static void Deserialize(IStream& stream, bool*& value) + { + value = new bool; + stream.Read(sizeof(*value), value); + } + + // time_t + static void Deserialize(IStream& stream, time_t& value) + { + stream.Read(sizeof(value), &value); + } + static void Deserialize(IStream& stream, time_t*& value) + { + value = new time_t; + stream.Read(sizeof(*value), value); + } + + // std::string + static void Deserialize(IStream& stream, std::string& str) + { + int length; + stream.Read(sizeof(length), &length); + char * buf = new char[length + 1]; + stream.Read(length, buf); + buf[length] = 0; + str = std::string(buf); + delete[] buf; + } + static void Deserialize(IStream& stream, std::string*& str) + { + int length; + stream.Read(sizeof(length), &length); + char * buf = new char[length + 1]; + stream.Read(length, buf); + buf[length] = 0; + str = new std::string(buf); + delete[] buf; + } + + // STL templates + + // std::list + template <typename T> + static void Deserialize(IStream& stream, std::list<T>& list) + { + int length; + stream.Read(sizeof(length), &length); + for (int i = 0; i < length; ++i) { + T obj; + Deserialize(stream, obj); + list.push_back(std::move(obj)); + } + } + template <typename T> + static void Deserialize(IStream& stream, std::list<T>*& list) + { + list = new std::list<T>; + Deserialize(stream, *list); + } + + // std::vector + template <typename T> + static void Deserialize(IStream& stream, std::vector<T>& vec) + { + int length; + stream.Read(sizeof(length), &length); + for (int i = 0; i < length; ++i) { + T obj; + Deserialize(stream, obj); + vec.push_back(std::move(obj)); + } + } + template <typename T> + static void Deserialize(IStream& stream, std::vector<T>*& vec) + { + vec = new std::vector<T>; + Deserialize(stream, *vec); + } + + // std::pair + template <typename A, typename B> + static void Deserialize(IStream& stream, std::pair<A, B>& p) + { + Deserialize(stream, p.first); + Deserialize(stream, p.second); + } + template <typename A, typename B> + static void Deserialize(IStream& stream, std::pair<A, B>*& p) + { + p = new std::pair<A, B>; + Deserialize(stream, *p); + } + + // std::map + template <typename K, typename T> + static void Deserialize(IStream& stream, std::map<K, T>& map) + { + int length; + stream.Read(sizeof(length), &length); + for (int i = 0; i < length; ++i) { + K key; + T obj; + Deserialize(stream, key); + Deserialize(stream, obj); + map[key] = std::move(obj); + } + } + template <typename K, typename T> + static void Deserialize(IStream& stream, std::map<K, T>*& map) + { + map = new std::map<K, T>; + Deserialize(stream, *map); + } +}; // struct Deserialization +} // namespace AuthPasswd + +#endif // SERIALIZATION_H diff --git a/src/dpl/core/include/dpl/singleton.h b/src/dpl/core/include/dpl/singleton.h new file mode 100644 index 0000000..2b42513 --- /dev/null +++ b/src/dpl/core/include/dpl/singleton.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011 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 singleton.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of singleton + */ +#ifndef AUTHPASSWD_SINGLETON_H +#define AUTHPASSWD_SINGLETON_H + +namespace AuthPasswd { +template<typename Class> +class Singleton : + private Class +{ + // + // Note: + // + // To remove posibility of instantiating directly Class, + // make Class' default constructor protected + // + + private: + Singleton() + {} + + static Singleton &InternalInstance(); + + public: + virtual ~Singleton() + {} + + static Class &Instance(); +}; +} // namespace AuthPasswd + +#endif // AUTHPASSWD_SINGLETON_H diff --git a/src/dpl/core/include/dpl/singleton_impl.h b/src/dpl/core/include/dpl/singleton_impl.h new file mode 100644 index 0000000..9f2e425 --- /dev/null +++ b/src/dpl/core/include/dpl/singleton_impl.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011 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 singleton_impl.h + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of singleton + */ +#ifndef AUTHPASSWD_SINGLETON_IMPL_H +#define AUTHPASSWD_SINGLETON_IMPL_H + +/* + * WARNING! + * + * If some singleton's implementation uses another singletons implementation, + * those templates make the second singleton a dubleton. Be warned. Try to use + * singleton_safe_impl.h if possible. + */ + +namespace AuthPasswd { +template<typename Class> +Singleton<Class>& Singleton<Class>::InternalInstance() +{ + static Singleton<Class> instance; + return instance; +} + +template<typename Class> +Class &Singleton<Class>::Instance() +{ + Singleton<Class>& instance = Singleton<Class>::InternalInstance(); + return instance; +} +} // namespace AuthPasswd + +#define IMPLEMENT_SINGLETON(Type) \ + template AuthPasswd::Singleton<Type>&AuthPasswd::Singleton<Type>::InternalInstance(); \ + template Type & AuthPasswd::Singleton<Type>::Instance(); \ + +#endif // AUTHPASSWD_SINGLETON_IMPL_H diff --git a/src/dpl/core/include/dpl/singleton_safe_impl.h b/src/dpl/core/include/dpl/singleton_safe_impl.h new file mode 100644 index 0000000..3ab2028 --- /dev/null +++ b/src/dpl/core/include/dpl/singleton_safe_impl.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2011 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 singleton_safe_impl.h + * @author Tomasz Swierczek (t.swierczek@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of singleton + */ +#ifndef AUTHPASSWD_SINGLETON_SAFE_IMPL_H +#define AUTHPASSWD_SINGLETON_SAFE_IMPL_H + +#define IMPLEMENT_SAFE_SINGLETON(Class) \ + namespace AuthPasswd { \ + template<> \ + Singleton<Class>&Singleton<Class>::InternalInstance() \ + { \ + static Singleton<Class> instance; \ + return instance; \ + } \ + \ + template<> \ + Class & Singleton<Class>::Instance() \ + { \ + Singleton<Class>& instance = Singleton<Class>::InternalInstance(); \ + return instance; \ + } \ + \ + template Singleton<Class>&Singleton<Class>::InternalInstance(); \ + template Class & Singleton<Class>::Instance(); \ + } // namespace AuthPasswd + +#endif // AUTHPASSWD_SINGLETON_SAFE_IMPL_H diff --git a/src/dpl/core/src/assert.cpp b/src/dpl/core/src/assert.cpp new file mode 100644 index 0000000..10b9ccb --- /dev/null +++ b/src/dpl/core/src/assert.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2011 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 assert.cpp + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of assert + */ +#include <stddef.h> +#include <dpl/assert.h> +#include <dpl/colors.h> +#include <dpl/log/log.h> +#include <dpl/exception.h> +#include <cstdlib> + +namespace AuthPasswd { +void AssertProc(const char *condition, + const char *file, + int line, + const char *function) +{ +#define INTERNAL_LOG(message) \ + do \ + { \ + std::ostringstream platformLog; \ + platformLog << message; \ + AuthPasswd::Log::LogSystemSingleton::Instance().Pedantic( \ + platformLog.str().c_str(), \ + __FILE__, __LINE__, __FUNCTION__); \ + } \ + while (0) + + // Try to log failed assertion to log system + Try + { + INTERNAL_LOG( + "################################################################################"); + INTERNAL_LOG( + "### AuthPasswd assertion failed! ###"); + INTERNAL_LOG( + "################################################################################"); + INTERNAL_LOG("### Condition: " << condition); + INTERNAL_LOG("### File: " << file); + INTERNAL_LOG("### Line: " << line); + INTERNAL_LOG("### Function: " << function); + INTERNAL_LOG( + "################################################################################"); + } catch (Exception) { + // Just ignore possible double errors + } + + // Fail with c-library abort + abort(); +} +} // namespace AuthPasswd diff --git a/src/dpl/core/src/binary_queue.cpp b/src/dpl/core/src/binary_queue.cpp new file mode 100644 index 0000000..12277d4 --- /dev/null +++ b/src/dpl/core/src/binary_queue.cpp @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2011 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 binary_queue.cpp + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of binary queue + */ +#include <stddef.h> +#include <dpl/binary_queue.h> +#include <dpl/assert.h> +#include <algorithm> +#include <malloc.h> +#include <cstring> +#include <new> + +namespace AuthPasswd { +BinaryQueue::BinaryQueue() : + m_size(0) +{} + +BinaryQueue::BinaryQueue(const BinaryQueue &other) : + m_size(0) +{ + AppendCopyFrom(other); +} + +BinaryQueue::~BinaryQueue() +{ + // Remove all remainig buckets + Clear(); +} + +const BinaryQueue &BinaryQueue::operator=(const BinaryQueue &other) +{ + if (this != &other) { + Clear(); + AppendCopyFrom(other); + } + + return *this; +} + +void BinaryQueue::AppendCopyFrom(const BinaryQueue &other) +{ + // To speed things up, always copy as one bucket + void *bufferCopy = malloc(other.m_size); + + if (bufferCopy == NULL) { + throw std::bad_alloc(); + } + + try { + other.Flatten(bufferCopy, other.m_size); + AppendUnmanaged(bufferCopy, other.m_size, &BufferDeleterFree, NULL); + } catch (const std::bad_alloc &) { + // Free allocated memory + free(bufferCopy); + throw; + } +} + +void BinaryQueue::AppendMoveFrom(BinaryQueue &other) +{ + // Copy all buckets + std::copy(other.m_buckets.begin(), + other.m_buckets.end(), std::back_inserter(m_buckets)); + m_size += other.m_size; + + // Clear other, but do not free memory + other.m_buckets.clear(); + other.m_size = 0; +} + +void BinaryQueue::AppendCopyTo(BinaryQueue &other) const +{ + other.AppendCopyFrom(*this); +} + +void BinaryQueue::AppendMoveTo(BinaryQueue &other) +{ + other.AppendMoveFrom(*this); +} + +void BinaryQueue::Clear() +{ + std::for_each(m_buckets.begin(), m_buckets.end(), &DeleteBucket); + m_buckets.clear(); + m_size = 0; +} + +void BinaryQueue::AppendCopy(const void* buffer, size_t bufferSize) +{ + // Create data copy with malloc/free + void *bufferCopy = malloc(bufferSize); + + // Check if allocation succeded + if (bufferCopy == NULL) { + throw std::bad_alloc(); + } + + // Copy user data + memcpy(bufferCopy, buffer, bufferSize); + + try { + // Try to append new bucket + AppendUnmanaged(bufferCopy, bufferSize, &BufferDeleterFree, NULL); + } catch (const std::bad_alloc &) { + // Free allocated memory + free(bufferCopy); + throw; + } +} + +void BinaryQueue::AppendUnmanaged(const void* buffer, + size_t bufferSize, + BufferDeleter deleter, + void* userParam) +{ + // Do not attach empty buckets + if (bufferSize == 0) { + deleter(buffer, bufferSize, userParam); + return; + } + + // Just add new bucket with selected deleter + Bucket *bucket = new Bucket(buffer, bufferSize, deleter, userParam); + try { + m_buckets.push_back(bucket); + } catch (const std::bad_alloc &) { + delete bucket; + throw; + } + + // Increase total queue size + m_size += bufferSize; +} + +size_t BinaryQueue::Size() const +{ + return m_size; +} + +bool BinaryQueue::Empty() const +{ + return m_size == 0; +} + +void BinaryQueue::Consume(size_t size) +{ + // Check parameters + if (size > m_size) { + Throw(Exception::OutOfData); + } + + size_t bytesLeft = size; + + // Consume data and/or remove buckets + while (bytesLeft > 0) { + // Get consume size + size_t count = std::min(bytesLeft, m_buckets.front()->left); + + m_buckets.front()->ptr = + static_cast<const char *>(m_buckets.front()->ptr) + count; + m_buckets.front()->left -= count; + bytesLeft -= count; + m_size -= count; + + if (m_buckets.front()->left == 0) { + DeleteBucket(m_buckets.front()); + m_buckets.pop_front(); + } + } +} + +void BinaryQueue::Flatten(void *buffer, size_t bufferSize) const +{ + // Check parameters + if (bufferSize == 0) { + return; + } + + if (bufferSize > m_size) { + Throw(Exception::OutOfData); + } + + size_t bytesLeft = bufferSize; + void *ptr = buffer; + BucketList::const_iterator bucketIterator = m_buckets.begin(); + Assert(m_buckets.end() != bucketIterator); + + // Flatten data + while (bytesLeft > 0) { + // Get consume size + size_t count = std::min(bytesLeft, (*bucketIterator)->left); + + // Copy data to user pointer + memcpy(ptr, (*bucketIterator)->ptr, count); + + // Update flattened bytes count + bytesLeft -= count; + ptr = static_cast<char *>(ptr) + count; + + // Take next bucket + ++bucketIterator; + } +} + +void BinaryQueue::FlattenConsume(void *buffer, size_t bufferSize) +{ + // FIXME: Optimize + Flatten(buffer, bufferSize); + Consume(bufferSize); +} + +void BinaryQueue::DeleteBucket(BinaryQueue::Bucket *bucket) +{ + delete bucket; +} + +void BinaryQueue::BufferDeleterFree(const void* data, + size_t dataSize, + void* userParam) +{ + (void)dataSize; + (void)userParam; + + // Default free deleter + free(const_cast<void *>(data)); +} + +BinaryQueue::Bucket::Bucket(const void* data, + size_t dataSize, + BufferDeleter dataDeleter, + void* userParam) : + buffer(data), + ptr(data), + size(dataSize), + left(dataSize), + deleter(dataDeleter), + param(userParam) +{ + Assert(data != NULL); + Assert(deleter != NULL); +} + +BinaryQueue::Bucket::~Bucket() +{ + // Invoke deleter on bucket data + deleter(buffer, size, param); +} + +BinaryQueue::BucketVisitor::~BucketVisitor() +{} + +BinaryQueue::BucketVisitorCall::BucketVisitorCall(BucketVisitor *visitor) : + m_visitor(visitor) +{} + +BinaryQueue::BucketVisitorCall::~BucketVisitorCall() +{} + +void BinaryQueue::BucketVisitorCall::operator()(Bucket *bucket) const +{ + m_visitor->OnVisitBucket(bucket->ptr, bucket->left); +} + +void BinaryQueue::VisitBuckets(BucketVisitor *visitor) const +{ + Assert(visitor != NULL); + + // Visit all buckets + std::for_each(m_buckets.begin(), m_buckets.end(), BucketVisitorCall(visitor)); +} + +BinaryQueueAutoPtr BinaryQueue::Read(size_t size) +{ + // Simulate input stream + size_t available = std::min(size, m_size); + + std::unique_ptr<void, std::function<void(void*)>> + bufferCopy(malloc(available), free); + + if (!bufferCopy.get()) { + throw std::bad_alloc(); + } + + BinaryQueueAutoPtr result(new BinaryQueue()); + + Flatten(bufferCopy.get(), available); + result->AppendUnmanaged( + bufferCopy.release(), available, &BufferDeleterFree, NULL); + Consume(available); + + return result; +} + +size_t BinaryQueue::Write(const BinaryQueue &buffer, size_t bufferSize) +{ + // Simulate output stream + AppendCopyFrom(buffer); + return bufferSize; +} +} // namespace AuthPasswd diff --git a/src/dpl/core/src/colors.cpp b/src/dpl/core/src/colors.cpp new file mode 100644 index 0000000..083ab37 --- /dev/null +++ b/src/dpl/core/src/colors.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2011 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 colors.cpp + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 1.0 + * @brief Some constants with definition of colors for Console + * and html output + */ +#include <stddef.h> +#include <dpl/colors.h> + +namespace AuthPasswd { +namespace Colors { +namespace Text { +const char* BOLD_GREEN_BEGIN = "\033[1;32m"; +const char* BOLD_GREEN_END = "\033[m"; +const char* RED_BEGIN = "\033[0;31m"; +const char* RED_END = "\033[m"; +const char* PURPLE_BEGIN = "\033[0;35m"; +const char* PURPLE_END = "\033[m"; +const char* GREEN_BEGIN = "\033[0;32m"; +const char* GREEN_END = "\033[m"; +const char* CYAN_BEGIN = "\033[0;36m"; +const char* CYAN_END = "\033[m"; +const char* BOLD_RED_BEGIN = "\033[1;31m"; +const char* BOLD_RED_END = "\033[m"; +const char* BOLD_YELLOW_BEGIN = "\033[1;33m"; +const char* BOLD_YELLOW_END = "\033[m"; +const char* BOLD_GOLD_BEGIN = "\033[0;33m"; +const char* BOLD_GOLD_END = "\033[m"; +const char* BOLD_WHITE_BEGIN = "\033[1;37m"; +const char* BOLD_WHITE_END = "\033[m"; +} //namespace Text + +namespace Html { +const char* BOLD_GREEN_BEGIN = "<font color=\"green\"><b>"; +const char* BOLD_GREEN_END = "</b></font>"; +const char* PURPLE_BEGIN = "<font color=\"purple\"><b>"; +const char* PURPLE_END = "</b></font>"; +const char* RED_BEGIN = "<font color=\"red\"><b>"; +const char* RED_END = "</b></font>"; +const char* GREEN_BEGIN = "<font color=\"green\">"; +const char* GREEN_END = "</font>"; +const char* CYAN_BEGIN = "<font color=\"cyan\">"; +const char* CYAN_END = "</font>"; +const char* BOLD_RED_BEGIN = "<font color=\"red\"><b>"; +const char* BOLD_RED_END = "</b></font>"; +const char* BOLD_YELLOW_BEGIN = "<font color=\"yellow\"><b>"; +const char* BOLD_YELLOW_END = "</b></font>"; +const char* BOLD_GOLD_BEGIN = "<font color=\"gold\"><b>"; +const char* BOLD_GOLD_END = "</b></font>"; +const char* BOLD_WHITE_BEGIN = "<font color=\"white\"><b>"; +const char* BOLD_WHITE_END = "</b></font>"; +} //namespace Html +} //namespace Colors +} //namespace AuthPasswd diff --git a/src/dpl/core/src/exception.cpp b/src/dpl/core/src/exception.cpp new file mode 100644 index 0000000..26f7385 --- /dev/null +++ b/src/dpl/core/src/exception.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2011 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 exception.cpp + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief This file is the implementation of exception system + */ +#include <stddef.h> +#include <dpl/exception.h> +#include <dpl/log/log.h> +#include <cstdio> + +namespace AuthPasswd { +Exception* Exception::m_lastException = NULL; +unsigned int Exception::m_exceptionCount = 0; +void (*Exception::m_terminateHandler)() = NULL; + +void LogUnhandledException(const std::string &str) +{ + // Logging to console + printf("%s\n", str.c_str()); + + // Logging to dlog + LogPedantic(str); +} + +void LogUnhandledException(const std::string &str, + const char *filename, + int line, + const char *function) +{ + // Logging to console + std::ostringstream msg; + msg << "\033[1;5;31m\n=== [" << filename << ":" << line << "] " << + function << " ===\033[m"; + msg << str; + printf("%s\n", msg.str().c_str()); + + // Logging to dlog + AuthPasswd::Log::LogSystemSingleton::Instance().Error( + str.c_str(), filename, line, function); +} +} // namespace AuthPasswd diff --git a/src/dpl/core/src/noncopyable.cpp b/src/dpl/core/src/noncopyable.cpp new file mode 100644 index 0000000..06c8772 --- /dev/null +++ b/src/dpl/core/src/noncopyable.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011 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 noncopyable.cpp + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of noncopyable + */ +#include <stddef.h> +#include <dpl/noncopyable.h> + +namespace AuthPasswd { +Noncopyable::Noncopyable() +{} + +Noncopyable::~Noncopyable() +{} +} // namespace AuthPasswd diff --git a/src/dpl/core/src/serialization.cpp b/src/dpl/core/src/serialization.cpp new file mode 100644 index 0000000..f8f05ff --- /dev/null +++ b/src/dpl/core/src/serialization.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011 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 serialization.cpp + * @author Tomasz Swierczek (t.swierczek@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of data serialization. + */ +#include <stddef.h> +#include <dpl/serialization.h> + +// +// Note: +// +// The file here is left blank to enable precompilation +// of templates in corresponding header file. +// Do not remove this file. +// diff --git a/src/dpl/core/src/singleton.cpp b/src/dpl/core/src/singleton.cpp new file mode 100644 index 0000000..a76e8ac --- /dev/null +++ b/src/dpl/core/src/singleton.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011 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 generic_event.cpp + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of singleton + */ +#include <stddef.h> +#include <dpl/singleton.h> + +// +// Note: +// +// The file here is left blank to enable precompilation +// of templates in corresponding header file. +// Do not remove this file. +// diff --git a/src/dpl/log/include/dpl/log/abstract_log_provider.h b/src/dpl/log/include/dpl/log/abstract_log_provider.h new file mode 100644 index 0000000..021d705 --- /dev/null +++ b/src/dpl/log/include/dpl/log/abstract_log_provider.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011 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 abstract_log_provider.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of abstract log provider + */ +#ifndef AUTHPASSWD_ABSTRACT_LOG_PROVIDER_H +#define AUTHPASSWD_ABSTRACT_LOG_PROVIDER_H + +namespace AuthPasswd { +namespace Log { +class AbstractLogProvider +{ + public: + virtual ~AbstractLogProvider() {} + + virtual void SetTag(const char *tag); + + virtual void Debug(const char *message, + const char *fileName, + int line, + const char *function) = 0; + virtual void Info(const char *message, + const char *fileName, + int line, + const char *function) = 0; + virtual void Warning(const char *message, + const char *fileName, + int line, + const char *function) = 0; + virtual void Error(const char *message, + const char *fileName, + int line, + const char *function) = 0; + virtual void Pedantic(const char *message, + const char *fileName, + int line, + const char *function) = 0; + virtual void SecureDebug(const char *message, + const char *fileName, + int line, + const char *function) = 0; + virtual void SecureInfo(const char *message, + const char *fileName, + int line, + const char *function) = 0; + virtual void SecureWarning(const char *message, + const char *fileName, + int line, + const char *function) = 0; + virtual void SecureError(const char *message, + const char *fileName, + int line, + const char *function) = 0; + + protected: + static const char *LocateSourceFileName(const char *filename); +}; +} +} // namespace AuthPasswd + +#endif // AUTHPASSWD_ABSTRACT_LOG_PROVIDER_H diff --git a/src/dpl/log/include/dpl/log/dlog_log_provider.h b/src/dpl/log/include/dpl/log/dlog_log_provider.h new file mode 100644 index 0000000..f87c7d5 --- /dev/null +++ b/src/dpl/log/include/dpl/log/dlog_log_provider.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2011 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 dlog_log_provider.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of DLOG log provider + */ +#ifndef AUTHPASSWD_DLOG_LOG_PROVIDER_H +#define AUTHPASSWD_DLOG_LOG_PROVIDER_H + +#include <dpl/log/abstract_log_provider.h> +#include <memory> +#include <string> + +namespace AuthPasswd { +namespace Log { +class DLOGLogProvider : + public AbstractLogProvider +{ + private: + std::unique_ptr<char[]> m_tag; + + static std::string FormatMessage(const char *message, + const char *filename, + int line, + const char *function); + + public: + DLOGLogProvider(); + virtual ~DLOGLogProvider(); + + 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); + + // Set global Tag according to DLOG + void SetTag(const char *tag); +}; + +} // namespace Log +} // namespace AuthPasswd + +#endif // AUTHPASSWD_DLOG_LOG_PROVIDER_H diff --git a/src/dpl/log/include/dpl/log/log.h b/src/dpl/log/include/dpl/log/log.h new file mode 100644 index 0000000..3af6a81 --- /dev/null +++ b/src/dpl/log/include/dpl/log/log.h @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2011 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 log.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of log system + */ +#ifndef AUTHPASSWD_LOG_H +#define AUTHPASSWD_LOG_H + +#include <dpl/singleton.h> +#include <dpl/noncopyable.h> +#include <dpl/log/abstract_log_provider.h> +#include <sstream> +#include <list> + +namespace AuthPasswd { +namespace Log { +/** + * AuthPasswd log system + * + * To switch logs into old style, export + * DPL_USE_OLD_STYLE_LOGS before application start + */ +class LogSystem : + private Noncopyable +{ + private: + typedef std::list<AbstractLogProvider *> AbstractLogProviderPtrList; + AbstractLogProviderPtrList m_providers; + + bool m_isLoggingEnabled; + + public: + bool IsLoggingEnabled() const; + LogSystem(); + virtual ~LogSystem(); + + /** + * Log debug message + */ + void Debug(const char *message, + const char *filename, + int line, + const char *function); + + /** + * Log info message + */ + void Info(const char *message, + const char *filename, + int line, + const char *function); + + /** + * Log warning message + */ + void Warning(const char *message, + const char *filename, + int line, + const char *function); + + /** + * Log error message + */ + void Error(const char *message, + const char *filename, + int line, + const char *function); + + /** + * Log pedantic message + */ + void Pedantic(const char *message, + const char *filename, + int line, + const char *function); + + /** + * Log pedantic message with secure macro + */ + void SecureDebug(const char *message, + const char *filename, + int line, + const char *function); + + /** + * Log info message with secure macro + */ + void SecureInfo(const char *message, + const char *filename, + int line, + const char *function); + + /** + * Log warning message with secure macro + */ + void SecureWarning(const char *message, + const char *filename, + int line, + const char *function); + + /** + * Log error message with secure macro + */ + void SecureError(const char *message, + const char *filename, + int line, + const char *function); + + /** + * Set default's DLOG provider Tag + */ + void SetTag(const char *tag); + + /** + * Add abstract provider to providers list + * + * @notice Ownership is transfered to LogSystem and deleted upon exit + */ + void AddProvider(AbstractLogProvider *provider); + + /** + * Remove abstract provider from providers list + */ + void RemoveProvider(AbstractLogProvider *provider); +}; + +/* + * Replacement low overhead null logging class + */ +class NullStream +{ + public: + NullStream() {} + + template <typename T> + NullStream& operator<<(const T&) + { + return *this; + } +}; + +/** + * Log system singleton + */ +typedef Singleton<LogSystem> LogSystemSingleton; +} +} // namespace AuthPasswd + +// +// Log support +// +// + +/* avoid warnings about unused variables */ +#define DPL_MACRO_DUMMY_LOGGING(message, function) \ + do { \ + AuthPasswd::Log::NullStream ns; \ + ns << message; \ + } while (0) + +#define DPL_MACRO_FOR_LOGGING(message, function) \ +do \ +{ \ + if (AuthPasswd::Log::LogSystemSingleton::Instance().IsLoggingEnabled()) \ + { \ + std::ostringstream platformLog; \ + platformLog << message; \ + AuthPasswd::Log::LogSystemSingleton::Instance().function( \ + platformLog.str().c_str(), \ + __FILE__, __LINE__, __FUNCTION__); \ + } \ +} while (0) + +/* Errors must be always logged. */ +#define LogError(message) DPL_MACRO_FOR_LOGGING(message, Error) +#define LogSecureError(message) DPL_MACRO_FOR_LOGGING(message, SecureError) + +#ifdef BUILD_TYPE_DEBUG + #define LogDebug(message) DPL_MACRO_FOR_LOGGING(message, Debug) + #define LogInfo(message) DPL_MACRO_FOR_LOGGING(message, Info) + #define LogWarning(message) DPL_MACRO_FOR_LOGGING(message, Warning) + #define LogPedantic(message) DPL_MACRO_FOR_LOGGING(message, Pedantic) + #define LogSecureDebug(message) DPL_MACRO_FOR_LOGGING(message, SecureDebug) + #define LogSecureInfo(message) DPL_MACRO_FOR_LOGGING(message, SecureInfo) + #define LogSecureWarning(message) DPL_MACRO_FOR_LOGGING(message, SecureWarning) +#else + #define LogDebug(message) DPL_MACRO_DUMMY_LOGGING(message, Debug) + #define LogInfo(message) DPL_MACRO_DUMMY_LOGGING(message, Info) + #define LogWarning(message) DPL_MACRO_DUMMY_LOGGING(message, Warning) + #define LogPedantic(message) DPL_MACRO_DUMMY_LOGGING(message, Pedantic) + #define LogSecureDebug(message) DPL_MACRO_DUMMY_LOGGING(message, SecureDebug) + #define LogSecureInfo(message) DPL_MACRO_DUMMY_LOGGING(message, SecureInfo) + #define LogSecureWarning(message) DPL_MACRO_DUMMY_LOGGING(message, SecureWarning) +#endif // BUILD_TYPE_DEBUG + +#endif // AUTHPASSWD_LOG_H diff --git a/src/dpl/log/include/dpl/log/old_style_log_provider.h b/src/dpl/log/include/dpl/log/old_style_log_provider.h new file mode 100644 index 0000000..39e58e6 --- /dev/null +++ b/src/dpl/log/include/dpl/log/old_style_log_provider.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2011 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 old_style_log_provider.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of old style log provider + */ +#ifndef AUTHPASSWD_OLD_STYLE_LOG_PROVIDER_H +#define AUTHPASSWD_OLD_STYLE_LOG_PROVIDER_H + +#include <dpl/log/abstract_log_provider.h> +#include <string> + +namespace AuthPasswd { +namespace Log { +class OldStyleLogProvider : + public AbstractLogProvider +{ + private: + bool m_showDebug; + bool m_showInfo; + bool m_showWarning; + bool m_showError; + bool m_showPedantic; + bool m_printStdErr; + + static std::string FormatMessage(const char *message, + const char *filename, + int line, + const char *function); + + public: + OldStyleLogProvider(bool showDebug, + bool showInfo, + bool showWarning, + bool showError, + bool showPedantic); + OldStyleLogProvider(bool showDebug, + bool showInfo, + bool showWarning, + bool showError, + bool showPedantic, + bool printStdErr); + virtual ~OldStyleLogProvider() {} + + 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); +}; +} +} // namespace AuthPasswd + +#endif // AUTHPASSWD_OLD_STYLE_LOG_PROVIDER_H diff --git a/src/dpl/log/src/abstract_log_provider.cpp b/src/dpl/log/src/abstract_log_provider.cpp new file mode 100644 index 0000000..7f7c07f --- /dev/null +++ b/src/dpl/log/src/abstract_log_provider.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2011 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 abstract_log_provider.cpp + * @author Pawel Sikorski (p.sikorski@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of abstract log provider + */ +#include <stddef.h> +#include <dpl/log/abstract_log_provider.h> +#include <cstring> + +#define UNUSED __attribute__((unused)) + +namespace AuthPasswd { +namespace Log { + +void AbstractLogProvider::SetTag(const char *tag UNUSED) {} + +const char *AbstractLogProvider::LocateSourceFileName(const char *filename) +{ + const char *ptr = strrchr(filename, '/'); + return ptr != NULL ? ptr + 1 : filename; +} +} +} diff --git a/src/dpl/log/src/dlog_log_provider.cpp b/src/dpl/log/src/dlog_log_provider.cpp new file mode 100644 index 0000000..a9cfc8f --- /dev/null +++ b/src/dpl/log/src/dlog_log_provider.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2011 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 dlog_log_provider.cpp + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of DLOG log provider + */ +#include <stddef.h> +#include <dpl/log/dlog_log_provider.h> +#include <cstring> +#include <sstream> +#include <dlog.h> + +#define UNUSED __attribute__((unused)) + +namespace AuthPasswd { +namespace Log { +std::string DLOGLogProvider::FormatMessage(const char *message, + const char *filename, + int line, + const char *function) +{ + std::ostringstream val; + + val << std::string("[") << + LocateSourceFileName(filename) << std::string(":") << line << + std::string("] ") << function << std::string("(): ") << message; + + return val.str(); +} + +DLOGLogProvider::DLOGLogProvider() +{} + +DLOGLogProvider::~DLOGLogProvider() +{} + +void DLOGLogProvider::SetTag(const char *tag) +{ + size_t size = strlen(tag)+1; + char *buff = new (std::nothrow) char[size]; + if (buff) + memcpy(buff, tag, size); + m_tag.reset(buff); +} + +void DLOGLogProvider::Debug(const char *message, + const char *filename, + int line, + const char *function) +{ + SLOG(LOG_DEBUG, m_tag.get(), "%s", + FormatMessage(message, filename, line, function).c_str()); +} + +void DLOGLogProvider::Info(const char *message, + const char *filename, + int line, + const char *function) +{ + SLOG(LOG_INFO, m_tag.get(), "%s", + FormatMessage(message, filename, line, function).c_str()); +} + +void DLOGLogProvider::Warning(const char *message, + const char *filename, + int line, + const char *function) +{ + SLOG(LOG_WARN, m_tag.get(), "%s", + FormatMessage(message, filename, line, function).c_str()); +} + +void DLOGLogProvider::Error(const char *message, + const char *filename, + int line, + const char *function) +{ + SLOG(LOG_ERROR, m_tag.get(), "%s", + FormatMessage(message, filename, line, function).c_str()); +} + +void DLOGLogProvider::Pedantic(const char *message, + const char *filename, + int line, + const char *function) +{ + SLOG(LOG_DEBUG, "AuthPasswd", "%s", FormatMessage(message, + filename, + line, + function).c_str()); +} + +void DLOGLogProvider::SecureDebug(const char *message UNUSED, + const char *filename UNUSED, + int line UNUSED, + const char *function UNUSED) +{ + SECURE_SLOG(LOG_DEBUG, m_tag.get(), "%s", + FormatMessage(message, filename, line, function).c_str()); +} + +void DLOGLogProvider::SecureInfo(const char *message UNUSED, + const char *filename UNUSED, + int line UNUSED, + const char *function UNUSED) +{ + SECURE_SLOG(LOG_INFO, m_tag.get(), "%s", + FormatMessage(message, filename, line, function).c_str()); +} + +void DLOGLogProvider::SecureWarning(const char *message UNUSED, + const char *filename UNUSED, + int line UNUSED, + const char *function UNUSED) +{ + SECURE_SLOG(LOG_WARN, m_tag.get(), "%s", + FormatMessage(message, filename, line, function).c_str()); +} + +void DLOGLogProvider::SecureError(const char *message UNUSED, + const char *filename UNUSED, + int line UNUSED, + const char *function UNUSED) +{ + SECURE_SLOG(LOG_ERROR, m_tag.get(), "%s", + FormatMessage(message, filename, line, function).c_str()); +} + +} // nemespace Log +} // namespace AuthPasswd diff --git a/src/dpl/log/src/log.cpp b/src/dpl/log/src/log.cpp new file mode 100644 index 0000000..cf4f256 --- /dev/null +++ b/src/dpl/log/src/log.cpp @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2011 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 log.cpp + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of log system + */ +#include <stddef.h> +#include <string.h> + +#include <dpl/log/log.h> +#include <dpl/singleton_impl.h> +#include <dpl/log/dlog_log_provider.h> +#include <dpl/log/old_style_log_provider.h> + +IMPLEMENT_SINGLETON(AuthPasswd::Log::LogSystem) + +namespace AuthPasswd { +namespace Log { +namespace // anonymous +{ +#ifdef BUILD_TYPE_DEBUG +const char *OLD_STYLE_LOGS_ENV_NAME = "DPL_USE_OLD_STYLE_LOGS"; +const char *OLD_STYLE_PEDANTIC_LOGS_ENV_NAME = + "DPL_USE_OLD_STYLE_PEDANTIC_LOGS"; +const char *OLD_STYLE_LOGS_MASK_ENV_NAME = "DPL_USE_OLD_STYLE_LOGS_MASK"; +#endif // BUILD_TYPE_DEBUG +const char *AUTH_PASSWD_LOG_OFF = "DPL_LOG_OFF"; +} // namespace anonymous + +bool LogSystem::IsLoggingEnabled() const +{ + return m_isLoggingEnabled; +} + +LogSystem::LogSystem() : + m_isLoggingEnabled(!getenv(AUTH_PASSWD_LOG_OFF)) +{ +#ifdef BUILD_TYPE_DEBUG + bool oldStyleLogs = false; + bool oldStyleDebugLogs = true; + bool oldStyleInfoLogs = true; + bool oldStyleWarningLogs = true; + bool oldStyleErrorLogs = true; + bool oldStylePedanticLogs = false; + + // Check environment settings about pedantic logs + const char *value = getenv(OLD_STYLE_LOGS_ENV_NAME); + + if (value != NULL && !strcmp(value, "1")) { + oldStyleLogs = true; + } + + value = getenv(OLD_STYLE_PEDANTIC_LOGS_ENV_NAME); + + if (value != NULL && !strcmp(value, "1")) { + oldStylePedanticLogs = true; + } + + value = getenv(OLD_STYLE_LOGS_MASK_ENV_NAME); + + if (value != NULL) { + size_t len = strlen(value); + + if (len >= 1) { + if (value[0] == '0') { + oldStyleDebugLogs = false; + } else if (value[0] == '1') { + oldStyleDebugLogs = true; + } + } + + if (len >= 2) { + if (value[1] == '0') { + oldStyleInfoLogs = false; + } else if (value[1] == '1') { + oldStyleInfoLogs = true; + } + } + + if (len >= 3) { + if (value[2] == '0') { + oldStyleWarningLogs = false; + } else if (value[2] == '1') { + oldStyleWarningLogs = true; + } + } + + if (len >= 4) { + if (value[3] == '0') { + oldStyleErrorLogs = false; + } else if (value[3] == '1') { + oldStyleErrorLogs = true; + } + } + } + + // Setup default DLOG and old style logging + if (oldStyleLogs) { + // Old style + AddProvider(new OldStyleLogProvider(oldStyleDebugLogs, + oldStyleInfoLogs, + oldStyleWarningLogs, + oldStyleErrorLogs, + oldStylePedanticLogs)); + } else { + // DLOG + AddProvider(new DLOGLogProvider()); + } +#else // BUILD_TYPE_DEBUG + AddProvider(new DLOGLogProvider()); +#endif // BUILD_TYPE_DEBUG +} + +LogSystem::~LogSystem() +{ + // Delete all providers + for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin(); + iterator != m_providers.end(); + ++iterator) + { + delete *iterator; + } + + m_providers.clear(); +} + +void LogSystem::SetTag(const char* tag) +{ + for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin(); + iterator != m_providers.end(); + ++iterator) + { + (*iterator)->SetTag(tag); + } +} + +void LogSystem::AddProvider(AbstractLogProvider *provider) +{ + m_providers.push_back(provider); +} + +void LogSystem::RemoveProvider(AbstractLogProvider *provider) +{ + m_providers.remove(provider); +} + +void LogSystem::Debug(const char *message, + const char *filename, + int line, + const char *function) +{ + for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin(); + iterator != m_providers.end(); + ++iterator) + { + (*iterator)->Debug(message, filename, line, function); + } +} + +void LogSystem::Info(const char *message, + const char *filename, + int line, + const char *function) +{ + for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin(); + iterator != m_providers.end(); + ++iterator) + { + (*iterator)->Info(message, filename, line, function); + } +} + +void LogSystem::Warning(const char *message, + const char *filename, + int line, + const char *function) +{ + for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin(); + iterator != m_providers.end(); + ++iterator) + { + (*iterator)->Warning(message, filename, line, function); + } +} + +void LogSystem::Error(const char *message, + const char *filename, + int line, + const char *function) +{ + for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin(); + iterator != m_providers.end(); + ++iterator) + { + (*iterator)->Error(message, filename, line, function); + } +} + +void LogSystem::Pedantic(const char *message, + const char *filename, + int line, + const char *function) +{ + for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin(); + iterator != m_providers.end(); + ++iterator) + { + (*iterator)->Pedantic(message, filename, line, function); + } +} + +void LogSystem::SecureInfo(const char *message, + const char *filename, + int line, + const char *function) +{ + for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin(); + iterator != m_providers.end(); + ++iterator) + { + (*iterator)->SecureInfo(message, filename, line, function); + } +} + +void LogSystem::SecureDebug(const char *message, + const char *filename, + int line, + const char *function) +{ + for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin(); + iterator != m_providers.end(); + ++iterator) + { + (*iterator)->SecureDebug(message, filename, line, function); + } +} + +void LogSystem::SecureError(const char *message, + const char *filename, + int line, + const char *function) +{ + for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin(); + iterator != m_providers.end(); + ++iterator) + { + (*iterator)->SecureError(message, filename, line, function); + } +} + +void LogSystem::SecureWarning(const char *message, + const char *filename, + int line, + const char *function) +{ + for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin(); + iterator != m_providers.end(); + ++iterator) + { + (*iterator)->SecureWarning(message, filename, line, function); + } +} + +} +} // namespace AuthPasswd diff --git a/src/dpl/log/src/old_style_log_provider.cpp b/src/dpl/log/src/old_style_log_provider.cpp new file mode 100644 index 0000000..fcdf111 --- /dev/null +++ b/src/dpl/log/src/old_style_log_provider.cpp @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2011 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 old_style_log_provider.cpp + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief This file is the implementation file of old style log provider + */ +#include <stddef.h> +#include <dpl/log/old_style_log_provider.h> +#include <dpl/colors.h> +#include <cstdio> +#include <cstring> +#include <sstream> +#include <sys/time.h> +#include <unistd.h> +#include <dlog.h> + +namespace AuthPasswd { +namespace Log { +namespace // anonymous +{ +using namespace AuthPasswd::Colors::Text; +const char *DEBUG_BEGIN = GREEN_BEGIN; +const char *DEBUG_END = GREEN_END; +const char *INFO_BEGIN = CYAN_BEGIN; +const char *INFO_END = CYAN_END; +const char *ERROR_BEGIN = RED_BEGIN; +const char *ERROR_END = RED_END; +const char *WARNING_BEGIN = BOLD_GOLD_BEGIN; +const char *WARNING_END = BOLD_GOLD_END; +const char *PEDANTIC_BEGIN = PURPLE_BEGIN; +const char *PEDANTIC_END = PURPLE_END; + +std::string GetFormattedTime() +{ + timeval tv; + tm localNowTime; + + gettimeofday(&tv, NULL); + localtime_r(&tv.tv_sec, &localNowTime); + + char format[64]; + snprintf(format, + sizeof(format), + "%02i:%02i:%02i.%03i", + localNowTime.tm_hour, + localNowTime.tm_min, + localNowTime.tm_sec, + static_cast<int>(tv.tv_usec / 1000)); + return format; +} +} // namespace anonymous + +std::string OldStyleLogProvider::FormatMessage(const char *message, + const char *filename, + int line, + const char *function) +{ + std::ostringstream val; + + val << std::string("[") << GetFormattedTime() << std::string("] [") << + static_cast<unsigned long>(pthread_self()) << "/" << + static_cast<int>(getpid()) << std::string("] [") << + LocateSourceFileName(filename) << std::string(":") << line << + std::string("] ") << function << std::string("(): ") << message; + + return val.str(); +} + +OldStyleLogProvider::OldStyleLogProvider(bool showDebug, + bool showInfo, + bool showWarning, + bool showError, + bool showPedantic) : + m_showDebug(showDebug), + m_showInfo(showInfo), + m_showWarning(showWarning), + m_showError(showError), + m_showPedantic(showPedantic), + m_printStdErr(false) +{} + +OldStyleLogProvider::OldStyleLogProvider(bool showDebug, + bool showInfo, + bool showWarning, + bool showError, + bool showPedantic, + bool printStdErr) : + m_showDebug(showDebug), + m_showInfo(showInfo), + m_showWarning(showWarning), + m_showError(showError), + m_showPedantic(showPedantic), + m_printStdErr(printStdErr) +{} + +void OldStyleLogProvider::Debug(const char *message, + const char *filename, + int line, + const char *function) +{ + if (m_showDebug) { + if (m_printStdErr) { + fprintf(stderr, "%s%s%s\n", DEBUG_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), DEBUG_END); + } else { + fprintf(stdout, "%s%s%s\n", DEBUG_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), DEBUG_END); + } + } +} + +void OldStyleLogProvider::Info(const char *message, + const char *filename, + int line, + const char *function) +{ + if (m_showInfo) { + if (m_printStdErr) { + fprintf(stderr, "%s%s%s\n", INFO_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), INFO_END); + } else { + fprintf(stdout, "%s%s%s\n", INFO_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), INFO_END); + } + } +} + +void OldStyleLogProvider::Warning(const char *message, + const char *filename, + int line, + const char *function) +{ + if (m_showWarning) { + if (m_printStdErr) { + fprintf(stderr, "%s%s%s\n", WARNING_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), WARNING_END); + } else { + fprintf(stdout, "%s%s%s\n", WARNING_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), WARNING_END); + } + } +} + +void OldStyleLogProvider::Error(const char *message, + const char *filename, + int line, + const char *function) +{ + if (m_showError) { + if (m_printStdErr) { + fprintf(stderr, "%s%s%s\n", ERROR_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), ERROR_END); + } else { + fprintf(stdout, "%s%s%s\n", ERROR_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), ERROR_END); + } + } +} + +void OldStyleLogProvider::Pedantic(const char *message, + const char *filename, + int line, + const char *function) +{ + if (m_showPedantic) { + if (m_printStdErr) { + fprintf(stderr, "%s%s%s\n", PEDANTIC_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), PEDANTIC_END); + } else { + fprintf(stdout, "%s%s%s\n", PEDANTIC_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), PEDANTIC_END); + } + } +} + +void OldStyleLogProvider::SecureDebug(const char *message, + const char *filename, + int line, + const char *function) +{ +#ifdef _SECURE_LOG + if (m_showDebug) { + if (m_printStdErr) { + fprintf(stderr, "%s%s%s\n", DEBUG_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), DEBUG_END); + } else { + fprintf(stdout, "%s%s%s\n", DEBUG_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), DEBUG_END); + } + } +#else + (void)message; + (void)filename; + (void)line; + (void)function; +#endif +} + +void OldStyleLogProvider::SecureInfo(const char *message, + const char *filename, + int line, + const char *function) +{ +#ifdef _SECURE_LOG + if (m_showInfo) { + if (m_printStdErr) { + fprintf(stderr, "%s%s%s\n", INFO_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), INFO_END); + } else { + fprintf(stdout, "%s%s%s\n", INFO_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), INFO_END); + } + } +#else + (void)message; + (void)filename; + (void)line; + (void)function; +#endif +} + +void OldStyleLogProvider::SecureWarning(const char *message, + const char *filename, + int line, + const char *function) +{ +#ifdef _SECURE_LOG + if (m_showWarning) { + if (m_printStdErr) { + fprintf(stderr, "%s%s%s\n", WARNING_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), WARNING_END); + } else { + fprintf(stdout, "%s%s%s\n", WARNING_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), WARNING_END); + } + } +#else + (void)message; + (void)filename; + (void)line; + (void)function; +#endif +} + +void OldStyleLogProvider::SecureError(const char *message, + const char *filename, + int line, + const char *function) +{ +#ifdef _SECURE_LOG + if (m_showError) { + if (m_printStdErr) { + fprintf(stderr, "%s%s%s\n", ERROR_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), ERROR_END); + } else { + fprintf(stdout, "%s%s%s\n", ERROR_BEGIN, + FormatMessage(message, filename, line, + function).c_str(), ERROR_END); + } + } +#else + (void)message; + (void)filename; + (void)line; + (void)function; +#endif +} + +} +} // namespace AuthPasswd diff --git a/src/include/CMakeLists.txt b/src/include/CMakeLists.txt new file mode 100644 index 0000000..3eeea74 --- /dev/null +++ b/src/include/CMakeLists.txt @@ -0,0 +1,7 @@ +INSTALL(FILES + ${INCLUDE_PATH}/auth-passwd.h + ${INCLUDE_PATH}/auth-passwd-admin.h + ${INCLUDE_PATH}/auth-passwd-policy-types.h + ${INCLUDE_PATH}/auth-passwd-error.h + DESTINATION /usr/include/authentication-server + ) diff --git a/src/include/auth-passwd-admin.h b/src/include/auth-passwd-admin.h new file mode 100644 index 0000000..1bc4503 --- /dev/null +++ b/src/include/auth-passwd-admin.h @@ -0,0 +1,88 @@ +/* + * Authentication password + * + * Copyright (c) 2016 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 AUTH_PASSWD_ADMIN_H +#define AUTH_PASSWD_ADMIN_H + +#include <sys/types.h> +#include <auth-passwd-error.h> +#include <auth-passwd-policy-types.h> + +/** + * @file auth-passwd-admin.h + * @version 1.0 + * @brief This file contains APIs of the Authentication Server +*/ + +/** + * @defgroup SecurityFW + * @{ + * + * @defgroup AUTH_PASSWD Authentication Server - password + * @version 1.0 + * @brief Authentication Server client library functions + * +*/ + +/** + * @addtogroup AUTH_PASSWD + * @{ +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +int auth_passwd_reset_passwd(const password_type passwd_type, + const uid_t uid, + const char *new_passwd); + +int auth_passwd_new_policy(policy_h **pp_policy); + +int auth_passwd_set_user(policy_h *p_policy, const uid_t uid); + +int auth_passwd_set_max_attempts(policy_h *p_policy, const unsigned int max_attempts); + +int auth_passwd_set_validity(policy_h *p_policy, const unsigned int valid_days); + +int auth_passwd_set_history_size(policy_h *p_policy, const unsigned int history_size); + +int auth_passwd_set_min_length(policy_h *p_policy, const unsigned int min_length); + +int auth_passwd_set_quality(policy_h *p_policy, password_quality_type quality_type); + +int auth_passwd_set_policy(policy_h *p_policy); + +void auth_passwd_free_policy(policy_h *p_policy); + +#ifdef __cplusplus +} +#endif + +/** + * @} +*/ + +/** + * @} +*/ + +#endif diff --git a/src/include/auth-passwd-error.h b/src/include/auth-passwd-error.h new file mode 100644 index 0000000..610f828 --- /dev/null +++ b/src/include/auth-passwd-error.h @@ -0,0 +1,85 @@ +/* + * Authentication password + * + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 AUTH_PASSWD_ERROR_H +#define AUTH_PASSWD_ERROR_H + +/** + * \name Return Codes + * exported by the foundation API. + * result codes begin with the start error code and extend into negative direction. + * @{ +*/ +#define AUTH_PASSWD_API_SUCCESS 0 + +/*! \brief indicating the result of the one specific API is successful */ +#define AUTH_PASSWD_API_ERROR_SOCKET -1 + +/*! \brief indicating the API's input parameter is malformed */ +#define AUTH_PASSWD_API_ERROR_INPUT_PARAM -2 + +/*! \brief indicating system is running out of memory state */ +#define AUTH_PASSWD_API_ERROR_OUT_OF_MEMORY -3 + +/*! \brief indicating the output buffer size which is passed as parameter is too small */ +#define Auth_PASSWD_API_ERROR_BUFFER_TOO_SMALL -4 + +/*! \brief indicating Authenticaton Server has been failed for some reason */ +#define AUTH_PASSWD_API_ERROR_SERVER_ERROR -5 + +/*! \brief indicating the access has been denied by Authetnication Server */ +#define AUTH_PASSWD_API_ERROR_ACCESS_DENIED -6 + +/*! \brief indicating there is no user */ +#define AUTH_PASSWD_API_ERROR_NO_USER -8 + +/*! \brief indicating there is no password set */ +#define AUTH_PASSWD_API_ERROR_NO_PASSWORD -9 + +/*! \brief indicating there is no recovery password set */ +#define AUTH_PASSWD_API_ERROR_NO_RECOVERY_PASSWORD -10 + +/*! \brief indicating password exists in system */ +#define AUTH_PASSWD_API_ERROR_PASSWORD_EXIST -11 + +/*! \brief indicating password mismatch */ +#define AUTH_PASSWD_API_ERROR_PASSWORD_MISMATCH -12 + +/*! \brief indicating password retry timeout is not occurred yet */ +#define AUTH_PASSWD_API_ERROR_PASSWORD_RETRY_TIMER -13 + +/*! \brief indicating password retry timeout is not occurred yet */ +#define AUTH_PASSWD_API_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED -14 + +/*! \brief indicating password retry timeout is not occurred yet */ +#define AUTH_PASSWD_API_ERROR_PASSWORD_EXPIRED -15 + +/*! \brief indicating password retry timeout is not occurred yet */ +#define AUTH_PASSWD_API_ERROR_PASSWORD_REUSED -16 + +/*! \brief indicating password retry timeout is not occurred yet */ +#define AUTH_PASSWD_API_ERROR_RECOVERY_PASSWORD_RESTRICTED -17 + +/*! \brief indicating the error with unknown reason */ +#define AUTH_PASSWD_API_ERROR_UNKNOWN -255 +/** @}*/ + +#endif diff --git a/src/include/auth-passwd-policy-types.h b/src/include/auth-passwd-policy-types.h new file mode 100644 index 0000000..7a7ea5e --- /dev/null +++ b/src/include/auth-passwd-policy-types.h @@ -0,0 +1,48 @@ +/* + * Authentication password + * + * Copyright (c) 2016 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 AUTH_PASSWD_POLICY_TYPES_H +#define AUTH_PASSWD_POLICY_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct auth_password_policy policy_h; + +typedef enum { + AUTH_PWD_NORMAL, + AUTH_PWD_RECOVERY +} password_type; + +typedef enum { + AUTH_PWD_QUALITY_UNSPECIFIED, + AUTH_PWD_QUALITY_SOMETHING, + AUTH_PWD_QUALITY_NUMERIC, + AUTH_PWD_QUALITY_ALPHABETIC, + AUTH_PWD_QUALITY_ALPHANUMERIC +} password_quality_type; + +#ifdef __cplusplus +} +#endif + +#endif /* AUTH_PASSWD_POLICY_TYPES_H */ diff --git a/src/include/auth-passwd.h b/src/include/auth-passwd.h new file mode 100644 index 0000000..9ea70f9 --- /dev/null +++ b/src/include/auth-passwd.h @@ -0,0 +1,88 @@ +/* + * Authentication password + * + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 AUTH_PASSWD_H +#define AUTH_PASSWD_H + +#include <sys/types.h> +#include <auth-passwd-error.h> +#include <auth-passwd-policy-types.h> + +/** + * @file auth-passwd.h + * @version 1.0 + * @brief This file contains APIs of the Authentication Server +*/ + +/** + * @defgroup SecurityFW + * @{ + * + * @defgroup AUTH_PASSWD Authentication Server - password + * @version 1.0 + * @brief Authentication Server client library functions + * +*/ + +/** + * @addtogroup AUTH_PASSWD + * @{ +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +int auth_passwd_check_passwd(const password_type passwd_type, + const char *passwd, + unsigned int *current_attempts, + unsigned int *max_attempts, + unsigned int *valid_secs); + +int auth_passwd_check_passwd_state(const password_type passwd_type, + unsigned int *current_attempts, + unsigned int *max_attempts, + unsigned int *valid_secs); + +int auth_passwd_check_passwd_reused(const password_type passwd_type, + const char *passwd, + int *is_reused); + +int auth_passwd_set_passwd(const password_type passwd_type, + const char *cur_passwd, + const char *new_passwd); + +int auth_passwd_set_passwd_recovery(const char *cur_recovery_passwd, + const char *new_normal_passwd); + +#ifdef __cplusplus +} +#endif + +/** + * @} +*/ + +/** + * @} +*/ + +#endif diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt new file mode 100644 index 0000000..72e99b7 --- /dev/null +++ b/src/server/CMakeLists.txt @@ -0,0 +1,47 @@ +PKG_CHECK_MODULES(SERVER_DEP + dlog + openssl + libsmack + libsystemd-daemon + libtzplatform-config + REQUIRED + ) +FIND_PACKAGE(Threads REQUIRED) + +INCLUDE_DIRECTORIES(SYSTEM + ${SERVER_DEP_INCLUDE_DIRS} + ) + +INCLUDE_DIRECTORIES( + ${INCLUDE_PATH} + ${COMMON_PATH}/include + ${SERVER_PATH}/main/include + ${SERVER_PATH}/service/include + ${DPL_PATH}/core/include + ${DPL_PATH}/log/include + ) + +SET(SERVER_SOURCES + ${SERVER_PATH}/main/generic-socket-manager.cpp + ${SERVER_PATH}/main/socket-manager.cpp + ${SERVER_PATH}/main/server-main.cpp + ${SERVER_PATH}/service/password.cpp + ${SERVER_PATH}/service/password-file.cpp + ${SERVER_PATH}/service/password-manager.cpp + ${SERVER_PATH}/service/password-file-buffer.cpp + ) + +SET_SOURCE_FILES_PROPERTIES( + ${SERVER_SOURCES} + PROPERTIES + COMPILE_FLAGS "-D_GNU_SOURCE -fvisibility=hidden -fPIE") + +ADD_EXECUTABLE(${TARGET_SERVER} ${SERVER_SOURCES}) + +TARGET_LINK_LIBRARIES(${TARGET_SERVER} + ${TARGET_COMMON} + ${CMAKE_THREAD_LIBS_INIT} + ${SERVER_DEP_LIBRARIES} -pie -ldl + ) + +INSTALL(TARGETS ${TARGET_SERVER} DESTINATION bin) diff --git a/src/server/main/generic-socket-manager.cpp b/src/server/main/generic-socket-manager.cpp new file mode 100644 index 0000000..1e0dbdd --- /dev/null +++ b/src/server/main/generic-socket-manager.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file generic-socket-manager.cpp + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + * @brief Implementation of GenericSocketService and GenericSocketManager. + */ + +#include <sys/socket.h> +#include <sys/types.h> + +#include <generic-socket-manager.h> + +namespace AuthPasswd { + +class SendMsgData::Internal { +public: + Internal(int resultCode, int fileDesc) + : m_resultCode(resultCode) + , m_fileDesc(fileDesc) + { + memset(&m_hdr, 0, sizeof(msghdr)); + memset(m_cmsgbuf, 0, CMSG_SPACE(sizeof(int))); + + m_iov.iov_base = &m_resultCode; + m_iov.iov_len = sizeof(m_resultCode); + + m_hdr.msg_iov = &m_iov; + m_hdr.msg_iovlen = 1; + + if (fileDesc != -1) { + m_hdr.msg_control = m_cmsgbuf; + m_hdr.msg_controllen = CMSG_SPACE(sizeof(int)); + + m_cmsg = CMSG_FIRSTHDR(&m_hdr); + m_cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + m_cmsg->cmsg_level = SOL_SOCKET; + m_cmsg->cmsg_type = SCM_RIGHTS; + + memmove(CMSG_DATA(m_cmsg), &m_fileDesc, sizeof(int)); + } + } + + msghdr* data() { return &m_hdr; } + +private: + msghdr m_hdr; + iovec m_iov; + cmsghdr *m_cmsg; + unsigned char m_cmsgbuf[CMSG_SPACE(sizeof(int))]; + int m_resultCode; + int m_fileDesc; +}; + +SendMsgData::SendMsgData() + : m_resultCode(0) + , m_fileDesc(-1) + , m_flags(0) + , m_pimpl(NULL) +{} + +SendMsgData::SendMsgData(int resultCode, int fileDesc, int paramFlags) + : m_resultCode(resultCode) + , m_fileDesc(fileDesc) + , m_flags(paramFlags) + , m_pimpl(NULL) +{} + +SendMsgData::SendMsgData(const SendMsgData &second) + : m_resultCode(second.m_resultCode) + , m_fileDesc(second.m_fileDesc) + , m_flags(second.m_flags) + , m_pimpl(NULL) +{} + +SendMsgData::~SendMsgData() { + delete m_pimpl; +} + +SendMsgData& SendMsgData::operator=(const SendMsgData &second) { + m_resultCode = second.m_resultCode; + m_fileDesc = second.m_fileDesc; + m_flags = second.m_flags; + delete m_pimpl; + m_pimpl = NULL; + return *this; +} + +msghdr* SendMsgData::getMsghdr() { + if (!m_pimpl) + m_pimpl = new Internal(m_resultCode, m_fileDesc); + return m_pimpl->data(); +} + +int SendMsgData::flags() { + return m_flags; +} + +} // namespace AuthPasswd + diff --git a/src/server/main/include/generic-event.h b/src/server/main/include/generic-event.h new file mode 100644 index 0000000..ef119fe --- /dev/null +++ b/src/server/main/include/generic-event.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file protocols.h + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + * @brief Implementation of GenericEvent. + */ + +#ifndef _AUTH_PASSWD_GENERIC_EVENT_ +#define _AUTH_PASSWD_GENERIC_EVENT_ + +namespace AuthPasswd { + +struct GenericEvent { + virtual ~GenericEvent(){} +}; + +} // namespace AuthPasswd + +#endif // _AUTH_PASSWD_GENERIC_EVENT_ diff --git a/src/server/main/include/generic-socket-manager.h b/src/server/main/include/generic-socket-manager.h new file mode 100644 index 0000000..f39e7a1 --- /dev/null +++ b/src/server/main/include/generic-socket-manager.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file generic-socket-manager.h + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + * @brief Implementation of GenericSocketService and GenericSocketManager. + */ + +#ifndef _AUTH_PASSWD_GENERIC_SERVICE_MANAGER_ +#define _AUTH_PASSWD_GENERIC_SERVICE_MANAGER_ + +#include <vector> +#include <string> + +#include <dpl/exception.h> + +#include <generic-event.h> + +extern "C" { +struct msghdr; +} // extern "C" + +namespace AuthPasswd { + +typedef int InterfaceID; + +struct ConnectionID { + int sock; // This is decriptor used for connection + int counter; // Unique handler per socket + inline bool operator<(const ConnectionID &second) const { + return counter < second.counter; + } + inline bool operator==(const ConnectionID &second) const { + return counter == second.counter; + } + inline bool operator!=(const ConnectionID &second) const { + return counter != second.counter; + } +}; + +typedef std::vector<unsigned char> RawBuffer; + +struct GenericSocketManager; + +struct GenericSocketService { + typedef std::string SmackLabel; + typedef std::string ServiceHandlerPath; + struct ServiceDescription { + ServiceDescription(const char *paramPath, + const char *paramSmackLabel, + InterfaceID paramInterfaceID = 0, + bool paramUseSendMsg = false) + : type(SOCKET_SERVICE), + interfaceID(paramInterfaceID), + useSendMsg(paramUseSendMsg), + smackLabel(paramSmackLabel), + serviceHandlerPath(paramPath), + fileDesc(-1) + {} + + ServiceDescription(int fileDesc, + InterfaceID paramInterfaceID = 0, + bool paramUseSendMsg = false) + : type(FILE_DESC_SERVICE), + interfaceID(paramInterfaceID), + useSendMsg(paramUseSendMsg), + fileDesc(fileDesc) + {} + + enum ServiceType { + SOCKET_SERVICE = 0, + FILE_DESC_SERVICE + }; + ServiceType type; + InterfaceID interfaceID; // All data from serviceHandlerPath will be marked with this interfaceHandler + bool useSendMsg; + + // if a socket service + SmackLabel smackLabel; // Smack label for socket + ServiceHandlerPath serviceHandlerPath; // Path to file + + // if a file descriptor + int fileDesc; + }; + + typedef std::vector<ServiceDescription> ServiceDescriptionVector; + + struct AcceptEvent : public GenericEvent { + ConnectionID connectionID; + InterfaceID interfaceID; + }; + + struct WriteEvent : public GenericEvent { + ConnectionID connectionID; + size_t size; + size_t left; + }; + + struct ReadEvent : public GenericEvent { + ConnectionID connectionID; + RawBuffer rawBuffer; + InterfaceID interfaceID; + }; + + struct CloseEvent : public GenericEvent { + ConnectionID connectionID; + }; + + virtual void SetSocketManager(GenericSocketManager *manager) { + m_serviceManager = manager; + } + + virtual ServiceDescriptionVector GetServiceDescription() = 0; + + virtual void Start() = 0; + virtual void Stop() = 0; + + virtual void Event(const AcceptEvent &event) = 0; + virtual void Event(const WriteEvent &event) = 0; + virtual void Event(const ReadEvent &event) = 0; + virtual void Event(const CloseEvent &event) = 0; + + GenericSocketService() : m_serviceManager(NULL) {} + virtual ~GenericSocketService(){} +protected: + GenericSocketManager *m_serviceManager; +}; + +class SendMsgData { +public: + class Internal; + + SendMsgData(); + SendMsgData(int resultCode, int fileDesc, int flags = 0); + SendMsgData(const SendMsgData &second); + SendMsgData& operator=(const SendMsgData &second); + virtual ~SendMsgData(); + + msghdr* getMsghdr(); + int flags(); +private: + int m_resultCode; + int m_fileDesc; + int m_flags; + Internal *m_pimpl; +}; + +struct GenericSocketManager { + virtual void MainLoop() = 0; + virtual void RegisterSocketService(GenericSocketService *ptr) = 0; + virtual void Close(ConnectionID connectionID) = 0; + virtual void Write(ConnectionID connectionID, const RawBuffer &rawBuffer) = 0; + virtual void Write(ConnectionID connectionID, const SendMsgData &sendMsgData) = 0; + virtual ~GenericSocketManager(){} +}; + +} // namespace AuthPasswd + +#endif // _AUTH_PASSWD_GENERIC_SERVICE_MANAGER_ diff --git a/src/server/main/include/service-thread.h b/src/server/main/include/service-thread.h new file mode 100644 index 0000000..ea9bfd2 --- /dev/null +++ b/src/server/main/include/service-thread.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file service-thread.h + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + * @brief Implementation of threads. + */ + +#ifndef _AUTH_PASSWD_SERVICE_THREAD_ +#define _AUTH_PASSWD_SERVICE_THREAD_ + +#include <cassert> +#include <queue> +#include <mutex> +#include <thread> +#include <memory> +#include <condition_variable> + +#include <cstdio> + +#include <dpl/exception.h> + +#include "generic-event.h" + +#define DEFINE_THREAD_EVENT(eventType) \ + void Event(const eventType &event) { \ + AuthPasswd::ServiceThread<ParentClassName>:: \ + Event(event, \ + this, \ + &ParentClassName::EventInternal##eventType); \ + } \ + void EventInternal##eventType(const eventType &event) + +#define DECLARE_THREAD_EVENT(eventType, methodName) \ + void Event(const eventType &event) { \ + AuthPasswd::ServiceThread<ParentClassName>:: \ + Event(event, \ + this, \ + &ParentClassName::methodName); \ + } + +namespace AuthPasswd { + +template <class Service> +class ServiceThread { +public: + typedef Service ParentClassName; + enum class State { + NoThread, + Work, + }; + + ServiceThread() + : m_state(State::NoThread) + , m_quit(false) + {} + + void Create() { + assert(m_state == State::NoThread); + m_thread = std::thread(ThreadLoopStatic, this); + m_state = State::Work; + } + + void Join() { + assert(m_state != State::NoThread); + { + std::lock_guard<std::mutex> lock(m_eventQueueMutex); + m_quit = true; + m_waitCondition.notify_one(); + } + m_thread.join(); + m_state = State::NoThread; + } + + virtual ~ServiceThread() + { + assert((m_state == State::NoThread) && "You must stop thread before destruction!"); + + while (!m_eventQueue.empty()){ + auto front = m_eventQueue.front(); + delete front.eventPtr; + m_eventQueue.pop(); + } + } + + template <class T> + void Event(const T &event, + Service *servicePtr, + void (Service::*serviceFunction)(const T &)) + { + EventDescription description; + description.serviceFunctionPtr = + reinterpret_cast<void (Service::*)(void*)>(serviceFunction); + description.servicePtr = servicePtr; + description.eventFunctionPtr = &ServiceThread::EventCall<T>; + description.eventPtr = new T(event); + { + std::lock_guard<std::mutex> lock(m_eventQueueMutex); + m_eventQueue.push(description); + } + m_waitCondition.notify_one(); + } + +protected: + + struct EventDescription { + void (Service::*serviceFunctionPtr)(void *); + Service *servicePtr; + void (ServiceThread::*eventFunctionPtr)(const EventDescription &event); + GenericEvent* eventPtr; + }; + + template <class T> + void EventCall(const EventDescription &desc) { + auto fun = reinterpret_cast<void (Service::*)(const T&)>(desc.serviceFunctionPtr); + const T& eventLocale = *(static_cast<T*>(desc.eventPtr)); + (desc.servicePtr->*fun)(eventLocale); + } + + static void ThreadLoopStatic(ServiceThread *ptr) { + ptr->ThreadLoop(); + } + + void ThreadLoop(){ + for (;;) { + EventDescription description = {NULL, NULL, NULL, NULL}; + { + std::unique_lock<std::mutex> ulock(m_eventQueueMutex); + if (m_quit) + return; + if (!m_eventQueue.empty()) { + description = m_eventQueue.front(); + m_eventQueue.pop(); + } else { + m_waitCondition.wait(ulock); + } + } + + if (description.eventPtr != NULL) { + UNHANDLED_EXCEPTION_HANDLER_BEGIN + { + (this->*description.eventFunctionPtr)(description); + delete description.eventPtr; + } + UNHANDLED_EXCEPTION_HANDLER_END + } + } + } + + std::thread m_thread; + std::mutex m_eventQueueMutex; + std::queue<EventDescription> m_eventQueue; + std::condition_variable m_waitCondition; + + State m_state; + bool m_quit; +}; + +} // namespace AuthPasswd + +#endif // _AUTH_PASSWD_SERVICE_THREAD_ diff --git a/src/server/main/include/socket-manager.h b/src/server/main/include/socket-manager.h new file mode 100644 index 0000000..75bc815 --- /dev/null +++ b/src/server/main/include/socket-manager.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file socket-manager.h + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + * @brief SocketManager implementation. + */ + +#ifndef _AUTH_PASSWD_SOCKET_MANAGER_ +#define _AUTH_PASSWD_SOCKET_MANAGER_ + +#include <vector> +#include <queue> +#include <string> +#include <mutex> +#include <thread> + +#include <dpl/exception.h> + +#include <generic-socket-manager.h> + +namespace AuthPasswd { + +class SocketManager : public GenericSocketManager { +public: + class Exception { + public: + DECLARE_EXCEPTION_TYPE(AuthPasswd::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, InitFailed) + }; + SocketManager(); + virtual ~SocketManager(); + virtual void MainLoop(); + virtual void MainLoopStop(); + + virtual void RegisterSocketService(GenericSocketService *service); + virtual void Close(ConnectionID connectionID); + virtual void Write(ConnectionID connectionID, const RawBuffer &rawBuffer); + virtual void Write(ConnectionID connectionID, const SendMsgData &sendMsgData); + +protected: + void CreateDomainSocket( + GenericSocketService *service, + const GenericSocketService::ServiceDescription &desc); + int CreateDomainSocketHelp( + const GenericSocketService::ServiceDescription &desc); + int GetSocketFromSystemD( + const GenericSocketService::ServiceDescription &desc); + + void ReadyForRead(int sock); + void ReadyForWrite(int sock); + void ReadyForWriteBuffer(int sock); + void ReadyForSendMsg(int sock); + void ReadyForAccept(int sock); + void ProcessQueue(void); + void NotifyMe(void); + void CloseSocket(int sock); + + struct SocketDescription { + bool isListen; + bool isOpen; + bool isTimeout; + bool useSendMsg; + InterfaceID interfaceID; + GenericSocketService *service; + time_t timeout; + RawBuffer rawBuffer; + std::queue<SendMsgData> sendMsgDataQueue; + int counter; + + SocketDescription() + : isListen(false) + , isOpen(false) + , isTimeout(false) + , useSendMsg(false) + , interfaceID(-1) + , service(NULL) + {} + }; + + SocketDescription& CreateDefaultReadSocketDescription(int sock, bool timeout, InterfaceID ifaceID = 0, GenericSocketService *service = NULL); + + typedef std::vector<SocketDescription> SocketDescriptionVector; + + struct WriteBuffer { + ConnectionID connectionID; + RawBuffer rawBuffer; + }; + + struct WriteData { + ConnectionID connectionID; + SendMsgData sendMsgData; + }; + + struct Timeout { + time_t time; + int sock; + bool operator<(const Timeout &second) const { + return time > second.time; // mininum first! + } + }; + + SocketDescriptionVector m_socketDescriptionVector; + fd_set m_readSet; + fd_set m_writeSet; + int m_maxDesc; + bool m_working; + std::mutex m_eventQueueMutex; + std::queue<WriteBuffer> m_writeBufferQueue; + std::queue<WriteData> m_writeDataQueue; + std::queue<ConnectionID> m_closeQueue; + int m_notifyMe[2]; + int m_counter; + std::priority_queue<Timeout> m_timeoutQueue; +}; + +} // namespace AuthPasswd + +#endif // _AUTH_PASSWD_SOCKET_MANAGER_ diff --git a/src/server/main/server-main.cpp b/src/server/main/server-main.cpp new file mode 100644 index 0000000..bf986a2 --- /dev/null +++ b/src/server/main/server-main.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file sever-main.cpp + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + * @brief Implementation of authentication server + */ +#include <stdlib.h> +#include <signal.h> + +#include <dpl/log/log.h> +#include <dpl/singleton.h> +#include <dpl/singleton_safe_impl.h> + +#include <socket-manager.h> + +#include <password.h> + +IMPLEMENT_SAFE_SINGLETON(AuthPasswd::Log::LogSystem); + +#define REGISTER_SOCKET_SERVICE(manager, service) \ + registerSocketService<service>(manager, #service) + +template<typename T> +void registerSocketService(AuthPasswd::SocketManager &manager, const std::string& serviceName) +{ + T *service = NULL; + try { + service = new T(); + service->Start(); + manager.RegisterSocketService(service); + service = NULL; + } catch (const AuthPasswd::Exception &exception) { + LogError("Error in creating service " << serviceName << + ", details:\n" << exception.DumpToString()); + } catch (const std::exception& e) { + LogError("Error in creating service " << serviceName << + ", details:\n" << e.what()); + } catch (...) { + LogError("Error in creating service " << serviceName << + ", unknown exception occured"); + } + if (service) + delete service; +} + +int main(void) { + + UNHANDLED_EXCEPTION_HANDLER_BEGIN + { + AuthPasswd::Singleton<AuthPasswd::Log::LogSystem>::Instance().SetTag("AUTH_PASSWD"); + + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGTERM); + sigaddset(&mask, SIGPIPE); + if (-1 == pthread_sigmask(SIG_BLOCK, &mask, NULL)) { + LogError("Error in pthread_sigmask"); + return 1; + } + + LogInfo("Start!"); + AuthPasswd::SocketManager manager; + + REGISTER_SOCKET_SERVICE(manager, AuthPasswd::PasswordService); + + manager.MainLoop(); + } + UNHANDLED_EXCEPTION_HANDLER_END + return 0; +} + diff --git a/src/server/main/socket-manager.cpp b/src/server/main/socket-manager.cpp new file mode 100644 index 0000000..76ac82a --- /dev/null +++ b/src/server/main/socket-manager.cpp @@ -0,0 +1,766 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file socket-manager.cpp + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + * @brief Implementation of SocketManager. + */ + +#include <set> + +#include <signal.h> +#include <sys/select.h> +#include <sys/signalfd.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 <fcntl.h> +#include <signal.h> +#include <errno.h> +#include <time.h> + +#include <systemd/sd-daemon.h> + +#include <dpl/log/log.h> +#include <dpl/assert.h> + +#include <error-description.h> +#include <smack-check.h> +#include <socket-manager.h> + +namespace { + +const time_t SOCKET_TIMEOUT = 300; + +} // namespace anonymous + +namespace AuthPasswd { + +struct DummyService : public GenericSocketService { + ServiceDescriptionVector GetServiceDescription() { + return ServiceDescriptionVector(); + } + + void Start() {} + void Stop() {} + + void Event(const AcceptEvent &event) { (void)event; } + void Event(const WriteEvent &event) { (void)event; } + void Event(const ReadEvent &event) { (void)event; } + void Event(const CloseEvent &event) { (void)event; } +}; + +struct SignalService : public GenericSocketService { + int GetDescriptor() { + LogInfo("set up"); + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGTERM); + if (-1 == pthread_sigmask(SIG_BLOCK, &mask, NULL)) + return -1; + return signalfd(-1, &mask, 0); + } + + ServiceDescriptionVector GetServiceDescription() { + return ServiceDescriptionVector(); + } + + void Start() {} + void Stop() {} + + void Event(const AcceptEvent &event) { (void)event; } // not supported + void Event(const WriteEvent &event) { (void)event; } // not supported + void Event(const CloseEvent &event) { (void)event; } // not supported + + void Event(const ReadEvent &event) { + LogDebug("Get signal information"); + + if(sizeof(struct signalfd_siginfo) != event.rawBuffer.size()) { + LogError("Wrong size of signalfd_siginfo struct. Expected: " + << sizeof(signalfd_siginfo) << " Get: " + << event.rawBuffer.size()); + return; + } + + const signalfd_siginfo *siginfo = reinterpret_cast<const signalfd_siginfo*>( + reinterpret_cast<const void*>(event.rawBuffer.data())); + + if (siginfo->ssi_signo == SIGTERM) { + LogInfo("Got signal: SIGTERM"); + static_cast<SocketManager*>(m_serviceManager)->MainLoopStop(); + return; + } + + LogInfo("This should not happend. Got signal: " << siginfo->ssi_signo); + } +}; + +SocketManager::SocketDescription& +SocketManager::CreateDefaultReadSocketDescription(int sock, bool timeout, InterfaceID ifaceID /*= 0*/, GenericSocketService *service /* = NULL*/) +{ + if ((int)m_socketDescriptionVector.size() <= sock) + m_socketDescriptionVector.resize(sock+20); + + auto &desc = m_socketDescriptionVector[sock]; + desc.isListen = false; + desc.isOpen = true; + desc.interfaceID = ifaceID; + desc.service = service; + desc.counter = ++m_counter; + + if (timeout) { + desc.timeout = time(NULL) + SOCKET_TIMEOUT; + if (false == desc.isTimeout) { + Timeout tm; + tm.time = desc.timeout; + tm.sock = sock; + m_timeoutQueue.push(tm); + } + } + + desc.isTimeout = timeout; + + FD_SET(sock, &m_readSet); + m_maxDesc = sock > m_maxDesc ? sock : m_maxDesc; + return desc; +} + +SocketManager::SocketManager() + : m_maxDesc(0) + , m_counter(0) +{ + FD_ZERO(&m_readSet); + FD_ZERO(&m_writeSet); + if (-1 == pipe(m_notifyMe)) { + int err = errno; + ThrowMsg(Exception::InitFailed, "Error in pipe: " << errnoToString(err)); + } + LogInfo("Pipe: Read desc: " << m_notifyMe[0] << " Write desc: " << m_notifyMe[1]); + + auto &desc = CreateDefaultReadSocketDescription(m_notifyMe[0], false); + desc.service = new DummyService; + + // std::thread bases on pthread so this should work fine + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGPIPE); + pthread_sigmask(SIG_BLOCK, &set, NULL); + + // add support for TERM signal (passed from systemd) + auto *signalService = new SignalService; + signalService->SetSocketManager(this); + int filefd = signalService->GetDescriptor(); + if (-1 == filefd) { + LogError("Error in SignalService.GetDescriptor()"); + delete signalService; + } else { + auto &desc2 = CreateDefaultReadSocketDescription(filefd, false); + desc2.service = signalService; + LogInfo("SignalService mounted on " << filefd << " descriptor"); + } +} + +SocketManager::~SocketManager() { + std::set<GenericSocketService*> serviceMap; + + // Find all services. Set is used to remove duplicates. + // In this implementation, services are not able to react in any way. + for (size_t i=0; i < m_socketDescriptionVector.size(); ++i) + if (m_socketDescriptionVector[i].isOpen) + serviceMap.insert(m_socketDescriptionVector[i].service); + + // Time to destroy all services. + for(auto service : serviceMap) { + LogDebug("delete " << (void*)(service)); + service->Stop(); + delete service; + } + + for (size_t i = 0; i < m_socketDescriptionVector.size(); ++i) + if (m_socketDescriptionVector[i].isOpen) + close(i); + + // All socket except one were closed. Now pipe input must be closed. + close(m_notifyMe[1]); +} + +void SocketManager::ReadyForAccept(int sock) { + struct sockaddr_un clientAddr; + unsigned int clientLen = sizeof(clientAddr); + int client = accept4(sock, (struct sockaddr*) &clientAddr, &clientLen, SOCK_NONBLOCK); +// LogInfo("Accept on sock: " << sock << " Socket opended: " << client); + if (-1 == client) { + int err = errno; + LogDebug("Error in accept: " << errnoToString(err)); + return; + } + + auto &desc = CreateDefaultReadSocketDescription(client, false); + desc.interfaceID = m_socketDescriptionVector[sock].interfaceID; + desc.service = m_socketDescriptionVector[sock].service; + desc.useSendMsg = m_socketDescriptionVector[sock].useSendMsg; + + GenericSocketService::AcceptEvent event; + event.connectionID.sock = client; + event.connectionID.counter = desc.counter; + event.interfaceID = desc.interfaceID; + desc.service->Event(event); +} + +void SocketManager::ReadyForRead(int sock) { + if (m_socketDescriptionVector[sock].isListen) { + ReadyForAccept(sock); + return; + } + + auto &desc = m_socketDescriptionVector[sock]; + GenericSocketService::ReadEvent event; + event.connectionID.sock = sock; + event.connectionID.counter = m_socketDescriptionVector[sock].counter; + event.interfaceID = desc.interfaceID; + event.rawBuffer.resize(4096); + + desc.timeout = time(NULL) + SOCKET_TIMEOUT; + + ssize_t size = read(sock, &event.rawBuffer[0], 4096); + + if (size == 0) { + CloseSocket(sock); + } else if (size >= 0) { + event.rawBuffer.resize(size); + desc.service->Event(event); + } else if (size == -1) { + int err = errno; + switch(err) { + case EAGAIN: + case EINTR: + break; + default: + LogDebug("Reading sock error: " << errnoToString(err)); + CloseSocket(sock); + } + } +} + +void SocketManager::ReadyForSendMsg(int sock) { + auto &desc = m_socketDescriptionVector[sock]; + + if (desc.sendMsgDataQueue.empty()) { + FD_CLR(sock, &m_writeSet); + return; + } + + auto data = desc.sendMsgDataQueue.front(); + ssize_t result = sendmsg(sock, data.getMsghdr(), data.flags()); + + if (result == -1) { + int err = errno; + switch(err) { + case EAGAIN: + case EINTR: + break; + case EPIPE: + default: + LogDebug("Error during send: " << errnoToString(err)); + CloseSocket(sock); + break; + } + return; + } else { + desc.sendMsgDataQueue.pop(); + } + + if (desc.sendMsgDataQueue.empty()) { + FD_CLR(sock, &m_writeSet); + } + + desc.timeout = time(NULL) + SOCKET_TIMEOUT; + + GenericSocketService::WriteEvent event; + event.connectionID.sock = sock; + event.connectionID.counter = desc.counter; + event.size = result; + event.left = desc.sendMsgDataQueue.size(); + + desc.service->Event(event); +} + +void SocketManager::ReadyForWriteBuffer(int sock) { + auto &desc = m_socketDescriptionVector[sock]; + size_t size = desc.rawBuffer.size(); + ssize_t result = write(sock, &desc.rawBuffer[0], size); + if (result == -1) { + int err = errno; + switch(err) { + case EAGAIN: + case EINTR: + // select will trigger write once again, nothing to do + break; + case EPIPE: + default: + LogDebug("Error during write: " << errnoToString(err)); + CloseSocket(sock); + break; + } + return; // We do not want to propagate error to next layer + } + + desc.rawBuffer.erase(desc.rawBuffer.begin(), desc.rawBuffer.begin()+result); + + desc.timeout = time(NULL) + SOCKET_TIMEOUT; + + if (desc.rawBuffer.empty()) + FD_CLR(sock, &m_writeSet); + + GenericSocketService::WriteEvent event; + event.connectionID.sock = sock; + event.connectionID.counter = desc.counter; + event.size = result; + event.left = desc.rawBuffer.size(); + + desc.service->Event(event); +} + +void SocketManager::ReadyForWrite(int sock) { + m_socketDescriptionVector[sock].useSendMsg ? + ReadyForSendMsg(sock) : ReadyForWriteBuffer(sock); +} + +void SocketManager::MainLoop() { + // remove evironment values passed by systemd + // uncomment it after removing old authentication password code + // sd_listen_fds(1); + + // Daemon is ready to work. + sd_notify(0, "READY=1"); + + m_working = true; + while(m_working) { + fd_set readSet = m_readSet; + fd_set writeSet = m_writeSet; + + timeval localTempTimeout; + timeval *ptrTimeout = &localTempTimeout; + + // I need to extract timeout from priority_queue. + // Timeout in priority_queue may be deprecated. + // I need to find some actual one. + while(!m_timeoutQueue.empty()) { + auto &top = m_timeoutQueue.top(); + auto &desc = m_socketDescriptionVector[top.sock]; + + if (top.time == desc.timeout) { + // This timeout matches timeout from socket. + // It can be used. + break; + } else { + // This socket was used after timeout in priority queue was set up. + // We need to update timeout and find some useable one. + Timeout tm = { desc.timeout , top.sock}; + m_timeoutQueue.pop(); + m_timeoutQueue.push(tm); + } + } + + if (m_timeoutQueue.empty()) { + LogDebug("No usaable timeout found."); + ptrTimeout = NULL; // select will wait without timeout + } else { + time_t currentTime = time(NULL); + auto &pqTimeout = m_timeoutQueue.top(); + + // 0 means that select won't block and socket will be closed ;-) + ptrTimeout->tv_sec = + currentTime < pqTimeout.time ? pqTimeout.time - currentTime : 0; + ptrTimeout->tv_usec = 0; +// LogDebug("Set up timeout: " << (int)ptrTimeout->tv_sec +// << " seconds. Socket: " << pqTimeout.sock); + } + + int ret = select(m_maxDesc+1, &readSet, &writeSet, NULL, ptrTimeout); + + if (0 == ret) { // timeout + Assert(!m_timeoutQueue.empty()); + + Timeout pqTimeout = m_timeoutQueue.top(); + m_timeoutQueue.pop(); + + auto &desc = m_socketDescriptionVector[pqTimeout.sock]; + + if (!desc.isTimeout || !desc.isOpen) { + // Connection was closed. Timeout is useless... + desc.isTimeout = false; + continue; + } + + if (pqTimeout.time < desc.timeout) { + // Is it possible? + // This socket was used after timeout. We need to update timeout. + pqTimeout.time = desc.timeout; + m_timeoutQueue.push(pqTimeout); + continue; + } + + // timeout from m_timeoutQueue matches with socket.timeout + // and connection is open. Time to close it! + // Putting new timeout in queue here is pointless. + desc.isTimeout = false; + CloseSocket(pqTimeout.sock); + + // All done. Now we should process next select ;-) + continue; + } + + if (-1 == ret) { + switch(errno) { + case EINTR: + LogDebug("EINTR in select"); + break; + default: + int err = errno; + LogError("Error in select: " << errnoToString(err)); + return; + } + continue; + } + for(int i = 0; i<m_maxDesc+1 && ret; ++i) { + if (FD_ISSET(i, &readSet)) { + ReadyForRead(i); + --ret; + } + if (FD_ISSET(i, &writeSet)) { + ReadyForWrite(i); + --ret; + } + } + ProcessQueue(); + } +} + +void SocketManager::MainLoopStop() +{ + m_working = false; + NotifyMe(); +} + +int SocketManager::GetSocketFromSystemD( + const GenericSocketService::ServiceDescription &desc) +{ + int fd; + + // TODO optimalization - do it once in object constructor + // and remember all information path->sockfd + int n = sd_listen_fds(0); + + LogInfo("sd_listen_fds returns: " << n); + + if (n < 0) { + LogError("Error in sd_listend_fds"); + ThrowMsg(Exception::InitFailed, "Error in sd_listend_fds"); + } + + for(fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START+n; ++fd) { + if (0 < sd_is_socket_unix(fd, SOCK_STREAM, 1, + desc.serviceHandlerPath.c_str(), 0)) + { + LogInfo("Useable socket " << desc.serviceHandlerPath << + " was passed by SystemD under descriptor " << fd); + + return fd; + } + } + LogInfo("No useable sockets were passed by systemd."); + return -1; +} + +int SocketManager::CreateDomainSocketHelp( + const GenericSocketService::ServiceDescription &desc) +{ + int sockfd; + + GenericSocketService::ServiceHandlerPath::size_type maxlen = + sizeof(static_cast<sockaddr_un*>(nullptr)->sun_path) / + sizeof(GenericSocketService::ServiceHandlerPath::value_type); + if(desc.serviceHandlerPath.size() >= maxlen) { + LogError("Service handler path too long: " << desc.serviceHandlerPath.size()); + ThrowMsg(Exception::InitFailed, + "Service handler path too long: " << desc.serviceHandlerPath.size()); + } + + if (-1 == (sockfd = socket(AF_UNIX, SOCK_STREAM, 0))) { + int err = errno; + LogError("Error in socket: " << errnoToString(err)); + ThrowMsg(Exception::InitFailed, "Error in socket: " << errnoToString(err)); + } + + if (smack_check()) { + LogInfo("Set up smack label: " << desc.smackLabel); + + 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))) + flags = 0; + + if (-1 == fcntl(sockfd, F_SETFL, flags | O_NONBLOCK)) { + int err = errno; + close(sockfd); + LogError("Error in fcntl: " << errnoToString(err)); + ThrowMsg(Exception::InitFailed, "Error in fcntl: " << errnoToString(err)); + } + + sockaddr_un serverAddress; + memset(&serverAddress, 0, sizeof(serverAddress)); + serverAddress.sun_family = AF_UNIX; + strcpy(serverAddress.sun_path, desc.serviceHandlerPath.c_str()); + unlink(serverAddress.sun_path); + + mode_t originalUmask; + originalUmask = umask(0); + + if (-1 == bind(sockfd, (struct sockaddr*)&serverAddress, sizeof(serverAddress))) { + int err = errno; + close(sockfd); + LogError("Error in bind: " << errnoToString(err)); + ThrowMsg(Exception::InitFailed, "Error in bind: " << errnoToString(err)); + } + + umask(originalUmask); + + if (-1 == listen(sockfd, 5)) { + int err = errno; + close(sockfd); + LogError("Error in listen: " << errnoToString(err)); + ThrowMsg(Exception::InitFailed, "Error in listen: " << errnoToString(err)); + } + + return sockfd; +} + +void SocketManager::CreateDomainSocket( + GenericSocketService *service, + const GenericSocketService::ServiceDescription &desc) +{ + int sockfd = GetSocketFromSystemD(desc); + if (-1 == sockfd) + sockfd = CreateDomainSocketHelp(desc); + + auto &description = CreateDefaultReadSocketDescription(sockfd, false); + + description.isListen = true; + description.interfaceID = desc.interfaceID; + description.useSendMsg = desc.useSendMsg; + description.service = service; + + LogDebug("Listen on socket: " << sockfd << + " Handler: " << desc.serviceHandlerPath.c_str()); +} + +void SocketManager::RegisterSocketService(GenericSocketService *service) { + service->SetSocketManager(this); + auto serviceVector = service->GetServiceDescription(); + Try { + for (auto iter = serviceVector.begin(); iter != serviceVector.end(); ++iter) + { + switch(iter->type) + { + case GenericSocketService::ServiceDescription::SOCKET_SERVICE: + CreateDomainSocket(service, *iter); + break; + case GenericSocketService::ServiceDescription::FILE_DESC_SERVICE: + CreateDefaultReadSocketDescription(iter->fileDesc, false, iter->interfaceID, service); + break; + default: + ThrowMsg(Exception::InitFailed, "Wrong service type in service description: " << iter->type); + break; + } + } + } Catch (Exception::Base) { + for (int i =0; i < (int)m_socketDescriptionVector.size(); ++i) + { + auto &desc = m_socketDescriptionVector[i]; + if (desc.service == service && desc.isOpen) { + close(i); + desc.isOpen = false; + } + } + ReThrow(Exception::Base); + } +} + +void SocketManager::Close(ConnectionID connectionID) { + { + std::lock_guard<std::mutex> ulock(m_eventQueueMutex); + m_closeQueue.push(connectionID); + } + NotifyMe(); +} + +void SocketManager::Write(ConnectionID connectionID, const RawBuffer &rawBuffer) { + WriteBuffer buffer; + buffer.connectionID = connectionID; + buffer.rawBuffer = rawBuffer; + { + std::lock_guard<std::mutex> ulock(m_eventQueueMutex); + m_writeBufferQueue.push(buffer); + } + NotifyMe(); +} + +void SocketManager::Write(ConnectionID connectionID, const SendMsgData &sendMsgData) { + WriteData data; + data.connectionID = connectionID; + data.sendMsgData = sendMsgData; + { + std::lock_guard<std::mutex> ulock(m_eventQueueMutex); + m_writeDataQueue.push(data); + } + NotifyMe(); +} + +void SocketManager::NotifyMe() { + TEMP_FAILURE_RETRY(write(m_notifyMe[1], "You have message ;-)", 1)); +} + +void SocketManager::ProcessQueue() { + WriteBuffer buffer; + WriteData data; + { + std::lock_guard<std::mutex> ulock(m_eventQueueMutex); + while (!m_writeBufferQueue.empty()) { + buffer = m_writeBufferQueue.front(); + m_writeBufferQueue.pop(); + + auto &desc = m_socketDescriptionVector[buffer.connectionID.sock]; + + if (!desc.isOpen) { + LogDebug("Received packet for write but connection is closed. Packet ignored!"); + continue; + } + + if (desc.counter != buffer.connectionID.counter) + { + LogDebug("Received packet for write but counter is broken. Packet ignored!"); + continue; + } + + if (desc.useSendMsg) { + LogError("Some service tried to push rawdata to socket that usees sendmsg!"); + continue; + } + + std::copy( + buffer.rawBuffer.begin(), + buffer.rawBuffer.end(), + std::back_inserter(desc.rawBuffer)); + + FD_SET(buffer.connectionID.sock, &m_writeSet); + } + + while(!m_writeDataQueue.empty()) { + data = m_writeDataQueue.front(); + m_writeDataQueue.pop(); + + auto &desc = m_socketDescriptionVector[data.connectionID.sock]; + + if (!desc.isOpen) { + LogDebug("Received packet for sendmsg but connection is closed. Packet ignored!"); + continue; + } + + if (desc.counter != data.connectionID.counter) + { + LogDebug("Received packet for write but counter is broken. Packet ignored!"); + continue; + } + + if (!desc.useSendMsg) { + LogError("Some service tries to push SendMsgData to socket that uses write!"); + continue; + } + + desc.sendMsgDataQueue.push(data.sendMsgData); + + FD_SET(data.connectionID.sock, &m_writeSet); + } + } + + while (1) { + ConnectionID connection; + { + std::lock_guard<std::mutex> ulock(m_eventQueueMutex); + if (m_closeQueue.empty()) + return; + connection = m_closeQueue.front(); + m_closeQueue.pop(); + } + + if (!m_socketDescriptionVector[connection.sock].isOpen) + continue; + + if (connection.counter != m_socketDescriptionVector[connection.sock].counter) + continue; + + CloseSocket(connection.sock); + } +} + +void SocketManager::CloseSocket(int sock) { +// LogInfo("Closing socket: " << sock); + auto &desc = m_socketDescriptionVector[sock]; + + if (!(desc.isOpen)) { + // This may happend when some information was waiting for write to the + // socket and in the same time socket was closed by the client. + LogError("Socket " << sock << " is not open. Nothing to do!"); + return; + } + + GenericSocketService::CloseEvent event; + event.connectionID.sock = sock; + event.connectionID.counter = desc.counter; + auto service = desc.service; + + desc.isOpen = false; + desc.service = NULL; + desc.interfaceID = -1; + desc.rawBuffer.clear(); + while(!desc.sendMsgDataQueue.empty()) + desc.sendMsgDataQueue.pop(); + + if (service) + service->Event(event); + else + LogError("Critical! Service is NULL! This should never happen!"); + + TEMP_FAILURE_RETRY(close(sock)); + FD_CLR(sock, &m_readSet); + FD_CLR(sock, &m_writeSet); +} + +} // namespace AuthPasswd diff --git a/src/server/service/include/password-exception.h b/src/server/service/include/password-exception.h new file mode 100644 index 0000000..417ce1e --- /dev/null +++ b/src/server/service/include/password-exception.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file password-exception.h + * @author Lukasz Kostyra (l.kostyra@partner.samsung.com) + * @version 1.0 + * @brief Definition of PasswordException class. + */ + +#ifndef _PASSWORD_EXCEPTION_H_ +#define _PASSWORD_EXCEPTION_H_ + +#include <dpl/exception.h> + +namespace AuthPasswd +{ + class PasswordException + { + public: + DECLARE_EXCEPTION_TYPE(AuthPasswd::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, OutOfData) + DECLARE_EXCEPTION_TYPE(Base, NoData) + DECLARE_EXCEPTION_TYPE(Base, FStreamOpenError) + DECLARE_EXCEPTION_TYPE(Base, FStreamWriteError) + DECLARE_EXCEPTION_TYPE(Base, FStreamReadError) + DECLARE_EXCEPTION_TYPE(Base, MemoryError) + DECLARE_EXCEPTION_TYPE(Base, NoPasswords) + DECLARE_EXCEPTION_TYPE(Base, PasswordNotActive) + DECLARE_EXCEPTION_TYPE(Base, MakeDirError) + DECLARE_EXCEPTION_TYPE(Base, ChmodError) + DECLARE_EXCEPTION_TYPE(Base, RemoveError) + DECLARE_EXCEPTION_TYPE(Base, TimerError) + }; +} //namespace AuthPasswd + +#endif //_PASSWORD_EXCEPTION_H_ diff --git a/src/server/service/include/password-file-buffer.h b/src/server/service/include/password-file-buffer.h new file mode 100644 index 0000000..10375b3 --- /dev/null +++ b/src/server/service/include/password-file-buffer.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file password-file-buffer.h + * @author Zbigniew Jasinski (z.jasinski@samsung.com) + * @author Lukasz Kostyra (l.kostyra@partner.samsung.com) + * @version 1.0 + * @brief Implementation of password file buffer, used for serialization in password-manager.h + */ + +#ifndef _PASSWORD_FILE_BUFFER_H_ +#define _PASSWORD_FILE_BUFFER_H_ + +#include <stddef.h> +#include <vector> +#include <string> + +#include <dpl/serialization.h> + +namespace AuthPasswd +{ + class PasswordFileBuffer: public IStream + { + public: + PasswordFileBuffer(); + + virtual void Read(size_t num, void *bytes); + virtual void Write(size_t num, const void *bytes); + + void Save(const std::string &path); + void Load(const std::string &path); + + private: + typedef std::vector<char> DataBuffer; + + DataBuffer m_buffer; + size_t m_bufferReadBytes; + }; +} //namespace AuthPasswd + +#endif diff --git a/src/server/service/include/password-file.h b/src/server/service/include/password-file.h new file mode 100644 index 0000000..9b18365 --- /dev/null +++ b/src/server/service/include/password-file.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file password-file.h + * @author Zbigniew Jasinski (z.jasinski@samsung.com) + * @author Lukasz Kostyra (l.kostyra@partner.samsung.com) + * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) + * @author Jooseong Lee (jooseong.lee@samsung.com) + * @version 1.0 + * @brief Implementation of PasswordFile, used to manage password files. + */ +#ifndef _PASSWORD_FILE_H_ +#define _PASSWORD_FILE_H_ + +#include <string> +#include <vector> +#include <list> +#include <chrono> +#include <memory> + +#include <time.h> + +#include <dpl/serialization.h> + +namespace AuthPasswd +{ + extern const time_t PASSWORD_INFINITE_EXPIRATION_TIME; + + struct IPassword: public ISerializable + { + typedef std::vector<unsigned char> RawHash; + + enum class PasswordType : unsigned int + { + NONE = 0, + SHA256 = 1, + }; + + virtual bool match(const std::string &password) const = 0; + }; + + typedef std::shared_ptr<IPassword> IPasswordPtr; + typedef std::list<IPasswordPtr> PasswordList; + + class PasswordFile + { + public: + PasswordFile(const unsigned int user); + + void writeMemoryToFile() const; + void writeAttemptToFile() const; + + void setPassword(const unsigned int passwdType, const std::string &password); + bool checkPassword(const unsigned int passwdType, const std::string &password) const; + + bool isPasswordActive(const unsigned int passwdType) const; + + void setMaxHistorySize(unsigned int history); + unsigned int getMaxHistorySize() const; + + unsigned int getExpireTimeLeft() const; + void setExpireTime(time_t expireTime); + + //attempt manipulating functions + unsigned int getAttempt() const; + void resetAttempt(); + void incrementAttempt(); + int getMaxAttempt() const; + void setMaxAttempt(unsigned int maxAttempt); + + bool isPasswordReused(const std::string &password) const; + + bool checkExpiration() const; + bool checkIfAttemptsExceeded() const; + bool isIgnorePeriod() const; + + bool isHistoryActive() const; + + private: +#if (__GNUC__ > 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 7)) + typedef std::chrono::steady_clock ClockType; +#else + typedef std::chrono::monotonic_clock ClockType; +#endif + typedef std::chrono::duration<double> TimeDiff; + typedef std::chrono::time_point<ClockType, TimeDiff> TimePoint; + + void loadMemoryFromFile(); + bool tryLoadMemoryFromOldFormatFile(); + + void resetTimer(); + void preparePwdFile(); + void prepareAttemptFile(); + void resetState(); + bool fileExists(const std::string &filename) const; + bool dirExists(const std::string &dirpath) const; + std::string createDir(const std::string &dir, const unsigned int user) const; + + mutable TimePoint m_retryTimerStart; + + //user name + const unsigned int m_user; + + //password file data + IPasswordPtr m_passwordCurrent; + IPasswordPtr m_passwordRecovery; + PasswordList m_passwordHistory; + unsigned int m_maxAttempt; + unsigned int m_maxHistorySize; + time_t m_expireTime; + bool m_passwordActive; + bool m_passwordRcvActive; + + //attempt file data + unsigned int m_attempt; + }; +} //namespace AuthPasswd + +#endif diff --git a/src/server/service/include/password-manager.h b/src/server/service/include/password-manager.h new file mode 100644 index 0000000..4832b57 --- /dev/null +++ b/src/server/service/include/password-manager.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file password-manager.h + * @author Zbigniew Jasinski (z.jasinski@samsung.com) + * @author Lukasz Kostyra (l.kostyra@partner.samsung.com) + * @author Jooseong Lee (jooseong.lee@samsung.com) + * @version 1.0 + * @brief Implementation of password management functions + */ + +#ifndef _PASSWORDMANAGER_H_ +#define _PASSWORDMANAGER_H_ + +#include <string> +#include <map> + +#include <password-file.h> + +namespace AuthPasswd +{ + class PasswordManager + { + public: + typedef std::map<unsigned int, PasswordFile> PasswordFileMap; + + //checking functions + //no const in checkPassword, attempts are update + int checkPassword(const unsigned int passwdType, const std::string& challenge, + const unsigned int currentUser, unsigned int ¤tAttempt, + unsigned int &maxAttempt, unsigned int &expirationTime); + int isPwdValid(const unsigned int passwdType, const unsigned int currentUser, + unsigned int ¤tAttempt, unsigned int &maxAttempt, + unsigned int &expirationTime); + int isPwdReused(const unsigned int passwdType, const std::string &passwd, + const unsigned int currentUser, bool &isReused); + + //setting functions + int setPassword(const unsigned int passwdType, const std::string ¤tPassword, + const std::string &newPassword, const unsigned int currentUser, + const unsigned int receivedAttempts, const unsigned int receivedDays, + const unsigned int receivedHistory); + int setPasswordRecovery(const std::string &curRcvPassword, const std::string &newPassword, + const unsigned int currentUser, const unsigned int receivedAttempts, + const unsigned int receivedDays, const unsigned int receivedHistory); + + //resetting functions + int resetPassword(const unsigned int passwdType, const std::string &newPassword, + const unsigned int receivedUser, const unsigned int receivedAttempts, + const unsigned int receivedDays, const unsigned int receivedHistory); + + //setting policy on the current passwd + int setPasswordMaxAttempts(const unsigned int receivedUser, + const unsigned int receivedAttempts); + int setPasswordValidity(const unsigned int receivedUser, const unsigned int receivedDays); + int setPasswordHistory(const unsigned int receivedUser, const unsigned int receivedHistory); + + private: + //managing functions + void addPassword(const unsigned int user); + void removePassword(const unsigned int user); + void existPassword(const unsigned int user); + + PasswordFileMap m_pwdFile; + }; +} //namespace AuthPasswd + +#endif diff --git a/src/server/service/include/password.h b/src/server/service/include/password.h new file mode 100644 index 0000000..1f69592 --- /dev/null +++ b/src/server/service/include/password.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file password.h + * @author Zigniew Jasinski (z.jasinski@samsung.com) + * @author Lukasz Kostyra (l.kostyra@partner.samsung.com) + * @author Jooseong Lee (jooseong.lee@samsung.com) + * @version 1.0 + * @brief Implementation of password service + */ + +#ifndef _PASSWORD_H_ +#define _PASSWORD_H_ + +#include <map> + +#include <service-thread.h> +#include <generic-socket-manager.h> +#include <message-buffer.h> +#include <connection-info.h> +#include <protocols.h> +#include <policy.h> + +#include <password-manager.h> + +namespace AuthPasswd +{ + class PasswordService + : public AuthPasswd::GenericSocketService + , public AuthPasswd::ServiceThread<PasswordService> + { + public: + class Exception + { + public: + DECLARE_EXCEPTION_TYPE(AuthPasswd::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, IncorrectHeader) + }; + + //service functions + ServiceDescriptionVector GetServiceDescription(); + + void Start(); + void Stop(); + + DECLARE_THREAD_EVENT(AcceptEvent, accept) + DECLARE_THREAD_EVENT(WriteEvent, write) + DECLARE_THREAD_EVENT(ReadEvent, process) + DECLARE_THREAD_EVENT(CloseEvent, close) + + void accept(const AcceptEvent &event); + void write(const WriteEvent &event); + void process(const ReadEvent &event); + void close(const CloseEvent &event); + + private: + //internal service functions + bool processOne(const ConnectionID &conn, MessageBuffer &buffer, InterfaceID interfaceID); + int processCheckFunctions(PasswordHdrs hdr, MessageBuffer& buffer, + const unsigned int cur_user, unsigned int &cur_att, + unsigned int &max_att, unsigned int &exp_time); + int processSetFunctions(PasswordHdrs hdr, MessageBuffer& buffer, + const unsigned int cur_user, bool &isPwdReused); + int processResetFunctions(PasswordHdrs hdr, MessageBuffer& buffer); + int processPolicyFunctions(PasswordHdrs hdr, MessageBuffer& buffer); + + // service attributes + PasswordManager m_pwdManager; + ConnectionInfoMap m_connectionInfoMap; + }; +} // namespace AuthPasswd + +#endif // _PASSWORD_H_ diff --git a/src/server/service/password-file-buffer.cpp b/src/server/service/password-file-buffer.cpp new file mode 100644 index 0000000..feefec2 --- /dev/null +++ b/src/server/service/password-file-buffer.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file password-file-buffer.h + * @author Lukasz Kostyra (l.kostyra@partner.samsung.com) + * @version 1.0 + * @brief Implementation of PasswordFileBuffer, used for serialization in PasswordFile class + */ + +#include <password-file-buffer.h> + +#include <fstream> +#include <iterator> + +#include <dpl/log/log.h> +#include <dpl/fstream_accessors.h> + +#include <auth-passwd-error.h> +#include <password-exception.h> + +#include <fcntl.h> +#include <string.h> +#include <unistd.h> + +namespace AuthPasswd +{ + PasswordFileBuffer::PasswordFileBuffer(): m_bufferReadBytes(0) {} + + void PasswordFileBuffer::Read(size_t num, void *bytes) + { + if(m_buffer.empty()) { + LogError("Buffer doesn't contain any data."); + Throw(PasswordException::NoData); + } + + if((m_bufferReadBytes + num) > m_buffer.size()) { + LogError("Not enough buffer to read " << num << " data."); + Throw(PasswordException::OutOfData); + } + + void* ret = memcpy(bytes, &m_buffer[m_bufferReadBytes], num); + + if(ret == 0) { + LogError("Failed to read " << num << " bytes."); + Throw(PasswordException::MemoryError); + } + + m_bufferReadBytes += num; + } + + void PasswordFileBuffer::Write(size_t num, const void *bytes) + { + const char* buffer = static_cast<const char*>(bytes); + std::copy(buffer, buffer+num, std::back_inserter(m_buffer)); + } + + void PasswordFileBuffer::Save(const std::string &path) + { + std::ofstream file(path, std::ofstream::trunc); + + if(!file.good()) { + LogError("Error while opening file stream."); + Throw(PasswordException::FStreamOpenError); + } + + file.write(m_buffer.data(), m_buffer.size()); + if(!file) { + LogError("Failed to write data."); + Throw(PasswordException::FStreamWriteError); + } + + file.flush(); + fsync(DPL::FstreamAccessors<std::ofstream>::GetFd(file)); // flush kernel space buffer + file.close(); + } + + void PasswordFileBuffer::Load(const std::string &path) + { + std::ifstream file(path, std::ifstream::binary); + + if(!file.good()) { + LogError("Error while opening file stream."); + Throw(PasswordException::FStreamOpenError); + } + + //reset read bytes counter + m_bufferReadBytes = 0; + + m_buffer.assign(std::istreambuf_iterator<char>(file), + std::istreambuf_iterator<char>()); + + if(!file) { + LogError("Failed to read data. Failbit: " << file.fail() << ", Badbit: " << file.bad()); + Throw(PasswordException::FStreamReadError); + } + } + +} //namespace AuthPasswd diff --git a/src/server/service/password-file.cpp b/src/server/service/password-file.cpp new file mode 100644 index 0000000..22a768d --- /dev/null +++ b/src/server/service/password-file.cpp @@ -0,0 +1,574 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file password-file.cpp + * @author Zbigniew Jasinski (z.jasinski@samsung.com) + * @author Lukasz Kostyra (l.kostyra@partner.samsung.com) + * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) + * @author Jooseong Lee (jooseong.lee@samsung.com) + * @version 1.0 + * @brief Implementation of PasswordFile, used to manage password files. + */ +#include <password-file.h> + +#include <fstream> +#include <algorithm> +#include <limits> + +#include <fcntl.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <tzplatform_config.h> +#include <openssl/sha.h> + +#include <dpl/log/log.h> +#include <dpl/fstream_accessors.h> + +#include <auth-passwd-policy-types.h> +#include <auth-passwd-error.h> + +#include <error-description.h> +#include <protocols.h> +#include <password-exception.h> +#include <password-file-buffer.h> + +namespace { + const std::string DATA_DIR = tzplatform_mkpath(TZ_SYS_DATA, "authentication-server"); + const std::string PASSWORD_FILE = "/password"; + const std::string OLD_VERSION_PASSWORD_FILE = "/password.old"; + const std::string ATTEMPT_FILE = "/attempt"; + const double RETRY_TIMEOUT = 0.5; + const mode_t FILE_MODE = S_IRUSR | S_IWUSR; + const unsigned int CURRENT_FILE_VERSION = 1; +} // namespace anonymous + +namespace AuthPasswd +{ + const time_t PASSWORD_INFINITE_EXPIRATION_TIME = std::numeric_limits<time_t>::max(); + + class NoPassword: public IPassword + { + public: + NoPassword(IStream&) {} + NoPassword() {} + + void Serialize(IStream &stream) const + { + Serialization::Serialize(stream, static_cast<unsigned int>(PasswordType::NONE)); + } + + bool match(const std::string &pass) const + { + return pass.empty(); + } + }; + + class SHA256Password: public IPassword + { + public: + SHA256Password(IStream& stream) + { + Deserialization::Deserialize(stream, m_hash); + } + + SHA256Password(const std::string &password) + : m_hash(hash(password)) {} + + SHA256Password(const RawHash& paramHash) + : m_hash(paramHash) {} + + void Serialize(IStream &stream) const + { + Serialization::Serialize(stream, static_cast<unsigned int>(PasswordType::SHA256)); + Serialization::Serialize(stream, m_hash); + } + + bool match(const std::string &password) const + { + return m_hash == hash(password); + } + private: + RawHash m_hash; + + static RawHash hash(const std::string &password) + { + RawHash result(SHA256_DIGEST_LENGTH); + + SHA256_CTX context; + SHA256_Init(&context); + SHA256_Update(&context, reinterpret_cast<const unsigned char*>(password.c_str()), + password.size()); + SHA256_Final(result.data(), &context); + + return result; + } + }; + + // deserialization of new password format + template <> + void Deserialization::Deserialize(IStream& stream, IPasswordPtr& ptr) + { + unsigned int algorithm; + Deserialization::Deserialize(stream, algorithm); + switch (algorithm) { + case (unsigned int)IPassword::PasswordType::NONE: + ptr.reset(new NoPassword()); + break; + case (unsigned int)IPassword::PasswordType::SHA256: + ptr.reset(new SHA256Password(stream)); + break; + default: + Throw(PasswordException::FStreamReadError); + } + } + + PasswordFile::PasswordFile(const unsigned int user): m_user(user), + m_passwordCurrent(new NoPassword()), + m_passwordRecovery(new NoPassword()), + m_maxAttempt(PASSWORD_INFINITE_ATTEMPT_COUNT), + m_maxHistorySize(0), + m_expireTime(PASSWORD_INFINITE_EXPIRATION_TIME), + m_passwordActive(false), + m_passwordRcvActive(false), + m_attempt(0) + { + // check if data directory exists + // if not create it + + std::string userDir = createDir(DATA_DIR.c_str(), m_user); + + if (!dirExists(DATA_DIR.c_str())) { + if(mkdir(DATA_DIR.c_str(), 0700)) { + LogError("Failed to create directory for files. Error: " << strerror(errno)); + Throw(PasswordException::MakeDirError); + } + } + + if (!dirExists(userDir.c_str())) { + if(mkdir(userDir.c_str(), 0700)) { + LogError("Failed to create directory for files. Error: " << strerror(errno)); + Throw(PasswordException::MakeDirError); + } + } + + preparePwdFile(); + prepareAttemptFile(); + resetTimer(); + } + + void PasswordFile::resetState() + { + m_maxAttempt = PASSWORD_INFINITE_ATTEMPT_COUNT; + m_maxHistorySize = 0; + m_expireTime = PASSWORD_INFINITE_EXPIRATION_TIME; + m_passwordRcvActive = false; + m_passwordRecovery.reset(new NoPassword()); + m_passwordActive = false; + m_passwordCurrent.reset(new NoPassword()); + } + + void PasswordFile::resetTimer() + { + m_retryTimerStart = ClockType::now(); + m_retryTimerStart -= TimeDiff(RETRY_TIMEOUT); + } + + void PasswordFile::preparePwdFile() + { + std::string pwdFile = createDir(DATA_DIR.c_str(), m_user) + PASSWORD_FILE; + std::string oldVersionPwdFile = createDir(DATA_DIR.c_str(), m_user) + OLD_VERSION_PASSWORD_FILE; + + // check if password file exists + if (!fileExists(pwdFile)) { + // if old format file exist - load it + if (tryLoadMemoryFromOldFormatFile()) { + // save in new format + writeMemoryToFile(); + // and remove old file + if (remove(oldVersionPwdFile.c_str())) { + LogError("Failed to remove file" << oldVersionPwdFile << + " Error: " << strerror(errno)); + Throw(PasswordException::RemoveError); + } + return; + } + LogSecureDebug("PWD_DBG not found " << m_user << " password file. Creating."); + + //create file + writeMemoryToFile(); + } else { //if file exists, load data + LogSecureDebug("PWD_DBG found " << m_user << " password file. Opening."); + try { + loadMemoryFromFile(); + } catch (...) { + LogError("Invalid " << pwdFile << " file format"); + resetState(); + writeMemoryToFile(); + } + } + } + + void PasswordFile::prepareAttemptFile() + { + std::string attemptFile = createDir(DATA_DIR.c_str(), m_user) + ATTEMPT_FILE; + + // check if attempt file exists + // if not create it + if (!fileExists(attemptFile)) { + LogSecureDebug("PWD_DBG not found " << m_user << " attempt file. Creating."); + writeAttemptToFile(); + } else { + LogSecureDebug("PWD_DBG found " << m_user << " attempt file. Opening."); + std::ifstream AttemptFile(attemptFile); + if(!AttemptFile) { + LogError("Failed to open " << m_user << " attempt file."); + // ignore error + return; + } + + AttemptFile.read(reinterpret_cast<char*>(&m_attempt), sizeof(unsigned int)); + if(!AttemptFile) { + LogError("Failed to read " << m_user <<" attempt count."); + // ignore error + resetAttempt(); + } + } + } + + bool PasswordFile::fileExists(const std::string &filename) const + { + struct stat buf; + + return ((stat(filename.c_str(), &buf) == 0)); + } + + bool PasswordFile::dirExists(const std::string &dirpath) const + { + struct stat buf; + + return ((stat(dirpath.c_str(), &buf) == 0) && (((buf.st_mode) & S_IFMT) == S_IFDIR)); + } + + std::string PasswordFile::createDir(const std::string &dir, const unsigned int user) const + { + std::string User = std::to_string(user); + return dir + "/" + User; + } + + void PasswordFile::writeMemoryToFile() const + { + PasswordFileBuffer pwdBuffer; + + LogSecureDebug("User: " << m_user << ", saving max_att: " << m_maxAttempt << + ", history_size: " << m_maxHistorySize << ", m_expireTime: " << + m_expireTime << ", isActive: " << m_passwordActive << + ", isRcvActive: " << m_passwordRcvActive); + + //serialize password attributes + Serialization::Serialize(pwdBuffer, CURRENT_FILE_VERSION); + Serialization::Serialize(pwdBuffer, m_maxAttempt); + Serialization::Serialize(pwdBuffer, m_maxHistorySize); + Serialization::Serialize(pwdBuffer, m_expireTime); + Serialization::Serialize(pwdBuffer, m_passwordRcvActive); + Serialization::Serialize(pwdBuffer, m_passwordRecovery); + Serialization::Serialize(pwdBuffer, m_passwordActive); + Serialization::Serialize(pwdBuffer, m_passwordCurrent); + Serialization::Serialize(pwdBuffer, m_passwordHistory); + + std::string pwdFile = createDir(DATA_DIR.c_str(), m_user) + PASSWORD_FILE; + pwdBuffer.Save(pwdFile); + + if (chmod(pwdFile.c_str(), FILE_MODE)) { + LogError("Failed to chmod for " << pwdFile << " Error: " << strerror(errno)); + Throw(PasswordException::ChmodError); + } + } + + void PasswordFile::loadMemoryFromFile() + { + PasswordFileBuffer pwdBuffer; + std::string pwdFile = createDir(DATA_DIR.c_str(), m_user) + PASSWORD_FILE; + + pwdBuffer.Load(pwdFile); + + unsigned int fileVersion = 0; + Deserialization::Deserialize(pwdBuffer, fileVersion); + if (fileVersion != CURRENT_FILE_VERSION) + Throw(PasswordException::FStreamReadError); + + m_passwordHistory.clear(); + + Deserialization::Deserialize(pwdBuffer, m_maxAttempt); + Deserialization::Deserialize(pwdBuffer, m_maxHistorySize); + Deserialization::Deserialize(pwdBuffer, m_expireTime); + Deserialization::Deserialize(pwdBuffer, m_passwordRcvActive); + Deserialization::Deserialize(pwdBuffer, m_passwordRecovery); + Deserialization::Deserialize(pwdBuffer, m_passwordActive); + Deserialization::Deserialize(pwdBuffer, m_passwordCurrent); + Deserialization::Deserialize(pwdBuffer, m_passwordHistory); + + LogSecureDebug("User: " << m_user << ", loaded max_att: " << m_maxAttempt << + ", history_size: " << m_maxHistorySize << ", m_expireTime: " << + m_expireTime << ", isActive: " << m_passwordActive << + ", isRcvActive: " << m_passwordRcvActive); + } + + bool PasswordFile::tryLoadMemoryFromOldFormatFile() + { + struct stat oldFileStat; + std::string oldVersionPwdFile = createDir(DATA_DIR.c_str(), m_user) + OLD_VERSION_PASSWORD_FILE; + + if (stat(oldVersionPwdFile.c_str(), &oldFileStat) != 0) + return false; + + static const int ELEMENT_SIZE = sizeof(unsigned) + SHA256_DIGEST_LENGTH; + static const int VERSION_1_REMAINING = sizeof(unsigned) * 4; + static const int VERSION_2_REMAINING = VERSION_1_REMAINING + sizeof(bool); + int remaining = oldFileStat.st_size % ELEMENT_SIZE; + + if (remaining != VERSION_1_REMAINING && remaining != VERSION_2_REMAINING) + return false; + + try { + PasswordFileBuffer pwdBuffer; + pwdBuffer.Load(oldVersionPwdFile); + + Deserialization::Deserialize(pwdBuffer, m_maxAttempt); + Deserialization::Deserialize(pwdBuffer, m_maxHistorySize); + Deserialization::Deserialize(pwdBuffer, m_expireTime); + if (m_expireTime == 0) + m_expireTime = PASSWORD_INFINITE_EXPIRATION_TIME; + + if (remaining == VERSION_2_REMAINING) + Deserialization::Deserialize(pwdBuffer, m_passwordActive); + else + m_passwordActive = true; + + // deserialize passwords in old format + struct OldPassword { + OldPassword() {} + OldPassword(IStream &stream) + { + Deserialization::Deserialize(stream, m_hash); + } + IPassword::RawHash m_hash; + }; + std::list<OldPassword> oldFormatPasswords; + Deserialization::Deserialize(pwdBuffer, oldFormatPasswords); + + // convert passwords to new format + m_passwordHistory.clear(); + if (oldFormatPasswords.empty()) { + m_passwordCurrent.reset(new NoPassword()); + m_passwordActive = false; + } else { + m_passwordCurrent.reset(new SHA256Password(oldFormatPasswords.front().m_hash)); + std::for_each(++oldFormatPasswords.begin(), oldFormatPasswords.end(), + [&] (const OldPassword& pwd) + {m_passwordHistory.push_back(IPasswordPtr(new SHA256Password(pwd.m_hash)));} + ); + } + + m_passwordRcvActive = false; + m_passwordRecovery.reset(new NoPassword()); + + } catch (...) { + LogWarning("Invalid " << oldVersionPwdFile << " file format"); + resetState(); + return false; + } + + return true; + } + + void PasswordFile::writeAttemptToFile() const + { + std::string attemptFile = createDir(DATA_DIR.c_str(), m_user) + ATTEMPT_FILE; + + std::ofstream AttemptFile(attemptFile, std::ofstream::trunc); + + if(!AttemptFile.good()) { + LogError("Failed to open " << m_user << " attempt file."); + Throw(PasswordException::FStreamOpenError); + } + + AttemptFile.write(reinterpret_cast<const char*>(&m_attempt), sizeof(unsigned int)); + if(!AttemptFile) { + LogError("Failed to write " << m_user << " attempt count."); + Throw(PasswordException::FStreamWriteError); + } + + AttemptFile.flush(); + fsync(DPL::FstreamAccessors<std::ofstream>::GetFd(AttemptFile)); // flush kernel space buffer + AttemptFile.close(); + } + + bool PasswordFile::isPasswordActive(const unsigned int passwdType) const + { + bool ret = false; + + if (passwdType == AUTH_PWD_NORMAL) + ret = m_passwordActive; + else if (passwdType == AUTH_PWD_RECOVERY) + ret = m_passwordRcvActive; + return ret; + } + + void PasswordFile::setMaxHistorySize(unsigned int history) + { + // put current password in history + if (m_maxHistorySize == 0 && history > 0) + m_passwordHistory.push_front(m_passwordCurrent); + + //setting history should be independent from password being set + m_maxHistorySize = history; + + while(m_passwordHistory.size() > history) + m_passwordHistory.pop_back(); + } + + unsigned int PasswordFile::getMaxHistorySize() const + { + return m_maxHistorySize; + } + + unsigned int PasswordFile::getAttempt() const + { + return m_attempt; + } + + void PasswordFile::resetAttempt() + { + m_attempt = 0; + } + + void PasswordFile::incrementAttempt() + { + m_attempt++; + } + + int PasswordFile::getMaxAttempt() const + { + return m_maxAttempt; + } + + void PasswordFile::setMaxAttempt(unsigned int maxAttempt) + { + m_maxAttempt = maxAttempt; + } + + bool PasswordFile::isPasswordReused(const std::string &password) const + { + LogSecureDebug("Checking if " << m_user << " pwd is reused. HistorySize: " << + m_passwordHistory.size() << ", MaxHistorySize: " << getMaxHistorySize()); + + //go through history and check if password existed earlier + if(std::any_of(m_passwordHistory.begin(), m_passwordHistory.end(), + [&password](const IPasswordPtr& pwd) { return pwd->match(password); })) { + LogSecureDebug(m_user << " passwords match!"); + return true; + } + + LogSecureDebug("isPasswordReused: No passwords match, " << m_user << + " password not reused."); + return false; + } + + void PasswordFile::setPassword(const unsigned int passwdType, const std::string &password) + { + if (passwdType == AUTH_PWD_NORMAL) { + //replace current password with new one + if (password.empty()) { + m_passwordCurrent.reset(new NoPassword()); + m_passwordActive = false; + } else { + m_passwordCurrent.reset(new SHA256Password(password)); + + //put current password to history + m_passwordHistory.push_front(m_passwordCurrent); + + //erase last password if we exceed max history size + if(m_passwordHistory.size() > getMaxHistorySize()) + m_passwordHistory.pop_back(); + m_passwordActive = true; + } + } else if (passwdType == AUTH_PWD_RECOVERY) { + //replace current password with new one + if (password.empty()) { + m_passwordRecovery.reset(new NoPassword()); + m_passwordRcvActive = false; + } else { + m_passwordRecovery.reset(new SHA256Password(password)); + m_passwordRcvActive = true; + } + } + } + + bool PasswordFile::checkPassword(const unsigned int passwdType, const std::string &password) const + { + bool ret = false; + if (passwdType == AUTH_PWD_NORMAL) + ret = m_passwordCurrent->match(password); + else if (passwdType == AUTH_PWD_RECOVERY) + ret = m_passwordRecovery->match(password); + return ret; + } + + void PasswordFile::setExpireTime(time_t expireTime) + { + m_expireTime = expireTime; + } + + unsigned int PasswordFile::getExpireTimeLeft() const + { + if(m_expireTime != PASSWORD_INFINITE_EXPIRATION_TIME) { + time_t timeLeft = m_expireTime - time(NULL); + return (timeLeft < 0) ? 0 : static_cast<unsigned int>(timeLeft); + } else + return PASSWORD_API_NO_EXPIRATION; + } + + bool PasswordFile::checkExpiration() const + { + //return true if expired, else false + return ((m_expireTime != PASSWORD_INFINITE_EXPIRATION_TIME) && (time(NULL) > m_expireTime)); + } + + bool PasswordFile::checkIfAttemptsExceeded() const + { + return ((m_maxAttempt != PASSWORD_INFINITE_ATTEMPT_COUNT) && (m_attempt > m_maxAttempt)); + } + + bool PasswordFile::isIgnorePeriod() const + { + TimePoint retryTimerStop = ClockType::now(); + TimeDiff diff = retryTimerStop - m_retryTimerStart; + + m_retryTimerStart = retryTimerStop; + + return (diff.count() < RETRY_TIMEOUT); + } + + bool PasswordFile::isHistoryActive() const + { + return (m_maxHistorySize != 0); + } +} //namespace AuthPasswd + diff --git a/src/server/service/password-manager.cpp b/src/server/service/password-manager.cpp new file mode 100644 index 0000000..2cc39f2 --- /dev/null +++ b/src/server/service/password-manager.cpp @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file password-manager.cpp + * @author Zbigniew Jasinski (z.jasinski@samsung.com) + * @author Lukasz Kostyra (l.kostyra@partner.samsung.com) + * @author Jooseong Lee (jooseong.lee@samsung.com) + * @version 1.0 + * @brief Implementation of password management functions + */ + +#include <password-manager.h> + +#include <iostream> +#include <iterator> +#include <algorithm> + +#include <limits.h> + +#include <dpl/log/log.h> + +#include <auth-passwd-policy-types.h> +#include <auth-passwd-error.h> + +#include <protocols.h> + +namespace { + bool calculateExpiredTime(unsigned int receivedDays, time_t &validSecs) + { + validSecs = AuthPasswd::PASSWORD_INFINITE_EXPIRATION_TIME; + + //when receivedDays means infinite expiration, return default validSecs value. + if(receivedDays == AuthPasswd::PASSWORD_INFINITE_EXPIRATION_DAYS) + return true; + + time_t curTime = time(NULL); + + if (receivedDays > ((UINT_MAX - curTime) / 86400)) { + LogError("Incorrect input param."); + return false; + } else { + validSecs = (curTime + (receivedDays * 86400)); + return true; + } + } +} //namespace + +namespace AuthPasswd +{ + void PasswordManager::addPassword(const unsigned int user) + { + m_pwdFile.insert(PasswordFileMap::value_type(user, PasswordFile(user))); + } + + void PasswordManager::removePassword(const unsigned int user) + { + m_pwdFile.erase(user); + } + + void PasswordManager::existPassword(const unsigned int user) + { + PasswordFileMap::iterator itPwd = m_pwdFile.find(user); + if (itPwd != m_pwdFile.end()) + return; + + addPassword(user); + return; + } + + int PasswordManager::checkPassword(const unsigned int passwdType, + const std::string &challenge, + const unsigned int currentUser, + unsigned int ¤tAttempt, + unsigned int &maxAttempt, + unsigned int &expirationTime) + { + LogSecureDebug("Inside checkPassword function."); + + existPassword(currentUser); + PasswordFileMap::iterator itPwd = m_pwdFile.find(currentUser); + + if (itPwd->second.isIgnorePeriod()) { + LogError("Retry timeout occurred."); + return AUTH_PASSWD_API_ERROR_PASSWORD_RETRY_TIMER; + } + if (!itPwd->second.isPasswordActive(passwdType) && !challenge.empty()) { + LogError("Password not active."); + return AUTH_PASSWD_API_ERROR_NO_PASSWORD; + } + + switch(passwdType) { + case AUTH_PWD_NORMAL: + + itPwd->second.incrementAttempt(); + itPwd->second.writeAttemptToFile(); + + currentAttempt = itPwd->second.getAttempt(); + maxAttempt = itPwd->second.getMaxAttempt(); + expirationTime = itPwd->second.getExpireTimeLeft(); + + if (itPwd->second.checkIfAttemptsExceeded()) { + LogError("Too many tries."); + return AUTH_PASSWD_API_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED; + } + if (!itPwd->second.checkPassword(AUTH_PWD_NORMAL, challenge)) { + LogError("Wrong password."); + return AUTH_PASSWD_API_ERROR_PASSWORD_MISMATCH; + } + + // Password maches and attempt number is fine - time to reset counter. + itPwd->second.resetAttempt(); + itPwd->second.writeAttemptToFile(); + + // Password is too old. You must change it before login. + if (itPwd->second.checkExpiration()) { + LogError("Password expired."); + return AUTH_PASSWD_API_ERROR_PASSWORD_EXPIRED; + } + break; + + case AUTH_PWD_RECOVERY: + if (!itPwd->second.checkPassword(AUTH_PWD_RECOVERY, challenge)) { + LogError("Wrong password."); + return AUTH_PASSWD_API_ERROR_PASSWORD_MISMATCH; + } + break; + + default: + LogError("Not supported password type."); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + return AUTH_PASSWD_API_SUCCESS; + } + + int PasswordManager::isPwdValid(const unsigned int passwdType, const unsigned int currentUser, + unsigned int ¤tAttempt, unsigned int &maxAttempt, + unsigned int &expirationTime) + { + existPassword(currentUser); + PasswordFileMap::iterator itPwd = m_pwdFile.find(currentUser); + + if (!itPwd->second.isPasswordActive(passwdType)) { + LogError("Current password not active."); + return AUTH_PASSWD_API_ERROR_NO_PASSWORD; + } + + switch(passwdType) { + case AUTH_PWD_NORMAL: + currentAttempt = itPwd->second.getAttempt(); + maxAttempt = itPwd->second.getMaxAttempt(); + expirationTime = itPwd->second.getExpireTimeLeft(); + break; + + case AUTH_PWD_RECOVERY: + // there are no maxAttempt and expirationTime for recovery password + currentAttempt = PASSWORD_INFINITE_ATTEMPT_COUNT; + maxAttempt = PASSWORD_INFINITE_ATTEMPT_COUNT; + expirationTime = PASSWORD_API_NO_EXPIRATION; + break; + + default: + LogError("Not supported password type."); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + return AUTH_PASSWD_API_SUCCESS; + } + + int PasswordManager::isPwdReused(const unsigned int passwdType, const std::string &passwd, + const unsigned int currentUser, bool &isReused) + { + existPassword(currentUser); + PasswordFileMap::iterator itPwd = m_pwdFile.find(currentUser); + + isReused = false; + + switch(passwdType) { + case AUTH_PWD_NORMAL: + // check history, however only if history is active and password is not empty + if (itPwd->second.isHistoryActive() && !passwd.empty()) + isReused = itPwd->second.isPasswordReused(passwd); + break; + + case AUTH_PWD_RECOVERY: + break; + + default: + LogError("Not supported password type."); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + return AUTH_PASSWD_API_SUCCESS; + } + + int PasswordManager::setPassword(const unsigned int passwdType, + const std::string ¤tPassword, + const std::string &newPassword, + const unsigned int currentUser, + const unsigned int receivedAttempts, + const unsigned int receivedDays, + const unsigned int receivedHistory) + { + LogSecureDebug("curUser = " << currentUser << ", pwdType = " << passwdType << + ", curPwd = " << currentPassword << ", newPwd = " << newPassword << + ", recAtt = " << receivedAttempts << ", recDays = " << receivedDays << + ", recHistory = " << receivedHistory); + + time_t valid_secs = 0; + + existPassword(currentUser); + PasswordFileMap::iterator itPwd = m_pwdFile.find(currentUser); + + if (itPwd->second.isIgnorePeriod()) { + LogError("Retry timeout occured."); + return AUTH_PASSWD_API_ERROR_PASSWORD_RETRY_TIMER; + } + + //check if passwords are correct + if (currentPassword.size() > MAX_PASSWORD_LEN) { + LogError("Current password length failed."); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + if (newPassword.size() > MAX_PASSWORD_LEN) { + LogError("New password length failed."); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + + // check delivered currentPassword + // when m_passwordActive flag is false, current password should be empty + if (!currentPassword.empty() && !itPwd->second.isPasswordActive(passwdType)) { + LogError("Password not active."); + return AUTH_PASSWD_API_ERROR_NO_PASSWORD; + } + + switch(passwdType) { + case AUTH_PWD_NORMAL: + // You remove password and set up recAttempts or recDays + if (newPassword.empty() && (receivedAttempts != 0 || receivedDays != 0)) { + LogError("Attempts or receivedDays is not equal 0"); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + + //increment attempt count before checking it against max attempt count + itPwd->second.incrementAttempt(); + itPwd->second.writeAttemptToFile(); + + if (itPwd->second.checkIfAttemptsExceeded()) { + LogError("Too many tries."); + return AUTH_PASSWD_API_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED; + } + + if (!itPwd->second.checkPassword(AUTH_PWD_NORMAL, currentPassword)) { + LogError("Wrong password."); + return AUTH_PASSWD_API_ERROR_PASSWORD_MISMATCH; + } + + //here we are sure that user knows current password - we can reset attempt counter + itPwd->second.resetAttempt(); + itPwd->second.writeAttemptToFile(); + + // check history, however only if history is active and new password is not empty + if (itPwd->second.isHistoryActive() && !newPassword.empty()) { + if (itPwd->second.isPasswordReused(newPassword)) { + LogError("Password reused."); + return AUTH_PASSWD_API_ERROR_PASSWORD_REUSED; + } + } + + if (!calculateExpiredTime(receivedDays, valid_secs)) { + LogError("Received expiration time incorrect."); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + + //setting password + itPwd->second.setPassword(AUTH_PWD_NORMAL, newPassword); + itPwd->second.setMaxAttempt(receivedAttempts); + itPwd->second.setExpireTime(valid_secs); + itPwd->second.setMaxHistorySize(receivedHistory); + itPwd->second.writeMemoryToFile(); + break; + + case AUTH_PWD_RECOVERY: + if (!itPwd->second.checkPassword(AUTH_PWD_RECOVERY, currentPassword)) { + LogError("Wrong password."); + return AUTH_PASSWD_API_ERROR_PASSWORD_MISMATCH; + } + itPwd->second.setPassword(AUTH_PWD_RECOVERY, newPassword); + itPwd->second.writeMemoryToFile(); + break; + + default: + LogError("Not supported password type."); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + return AUTH_PASSWD_API_SUCCESS; + } + + int PasswordManager::setPasswordRecovery(const std::string &curRcvPassword, + const std::string &newPassword, + const unsigned int currentUser, + const unsigned int receivedAttempts, + const unsigned int receivedDays, + const unsigned int receivedHistory) + { + LogSecureDebug("curUser = " << currentUser << ", curPwd = " << curRcvPassword << + ", newPwd = " << newPassword << ", recAtt = " << receivedAttempts << + ", recDays = " << receivedDays << ", recHistory = " << receivedHistory); + + time_t valid_secs = 0; + + existPassword(currentUser); + PasswordFileMap::iterator itPwd = m_pwdFile.find(currentUser); + + if (itPwd->second.isIgnorePeriod()) { + LogError("Retry timeout occured."); + return AUTH_PASSWD_API_ERROR_PASSWORD_RETRY_TIMER; + } + + //check if passwords are correct + if (curRcvPassword.size() > MAX_PASSWORD_LEN || curRcvPassword.empty()) { + LogError("Current recovery password length failed."); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + if (newPassword.size() > MAX_PASSWORD_LEN || newPassword.empty()) { + LogError("New password length failed."); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + + // current recovery password should be existed. + if (!itPwd->second.isPasswordActive(AUTH_PWD_RECOVERY)) { + LogError("Password not active."); + return AUTH_PASSWD_API_ERROR_NO_PASSWORD; + } + + if (!itPwd->second.checkPassword(AUTH_PWD_RECOVERY, curRcvPassword)) { + LogError("Wrong password."); + return AUTH_PASSWD_API_ERROR_PASSWORD_MISMATCH; + } + + // check history, however only if history is active and new password is not empty + if (itPwd->second.isHistoryActive()) { + if (itPwd->second.isPasswordReused(newPassword)) { + LogError("Password reused."); + return AUTH_PASSWD_API_ERROR_PASSWORD_REUSED; + } + } + + if (!calculateExpiredTime(receivedDays, valid_secs)) { + LogError("Received expiration time incorrect."); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + + itPwd->second.resetAttempt(); + itPwd->second.writeAttemptToFile(); + + //setting password + itPwd->second.setPassword(AUTH_PWD_NORMAL, newPassword); + itPwd->second.setMaxAttempt(receivedAttempts); + itPwd->second.setExpireTime(valid_secs); + itPwd->second.setMaxHistorySize(receivedHistory); + itPwd->second.writeMemoryToFile(); + + return AUTH_PASSWD_API_SUCCESS; + } + + int PasswordManager::resetPassword(const unsigned int passwdType, + const std::string &newPassword, + const unsigned int receivedUser, + const unsigned int receivedAttempts, + const unsigned int receivedDays, + const unsigned int receivedHistory) + { + time_t valid_secs = 0; + + existPassword(receivedUser); + PasswordFileMap::iterator itPwd = m_pwdFile.find(receivedUser); + + switch(passwdType) { + case AUTH_PWD_NORMAL: + if (!calculateExpiredTime(receivedDays, valid_secs)) + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + + if (newPassword.empty() && (receivedAttempts != 0 || receivedDays != 0)) { + LogError("Attempts or receivedDays is not equal 0"); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + itPwd->second.resetAttempt(); + itPwd->second.writeAttemptToFile(); + itPwd->second.setPassword(AUTH_PWD_NORMAL, newPassword); + itPwd->second.setMaxAttempt(receivedAttempts); + itPwd->second.setExpireTime(valid_secs); + itPwd->second.setMaxHistorySize(receivedHistory); + itPwd->second.writeMemoryToFile(); + break; + + case AUTH_PWD_RECOVERY: + itPwd->second.setPassword(AUTH_PWD_RECOVERY, newPassword); + itPwd->second.writeMemoryToFile(); + break; + + default: + LogError("Not supported password type."); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + return AUTH_PASSWD_API_SUCCESS; + } + + int PasswordManager::setPasswordMaxAttempts(const unsigned int receivedUser, + const unsigned int receivedAttempts) + { + existPassword(receivedUser); + PasswordFileMap::iterator itPwd = m_pwdFile.find(receivedUser); + + // check if there is password + if (!itPwd->second.isPasswordActive(AUTH_PWD_NORMAL)) { + LogError("Password not active."); + return AUTH_PASSWD_API_ERROR_NO_PASSWORD; + } + + itPwd->second.setMaxAttempt(receivedAttempts); + itPwd->second.writeMemoryToFile(); + + itPwd->second.resetAttempt(); + itPwd->second.writeAttemptToFile(); + + return AUTH_PASSWD_API_SUCCESS; + } + + int PasswordManager::setPasswordValidity(const unsigned int receivedUser, + const unsigned int receivedDays) + { + time_t valid_secs = 0; + + LogSecureDebug("received_days: " << receivedDays); + + existPassword(receivedUser); + PasswordFileMap::iterator itPwd = m_pwdFile.find(receivedUser); + + if (!itPwd->second.isPasswordActive(AUTH_PWD_NORMAL)) { + LogError("Current password is not active."); + return AUTH_PASSWD_API_ERROR_NO_PASSWORD; + } + + if (!calculateExpiredTime(receivedDays, valid_secs)) + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + + itPwd->second.setExpireTime(valid_secs); + itPwd->second.writeMemoryToFile(); + + return AUTH_PASSWD_API_SUCCESS; + } + + int PasswordManager::setPasswordHistory(const unsigned int receivedUser, + const unsigned int receivedHistory) + { + existPassword(receivedUser); + PasswordFileMap::iterator itPwd = m_pwdFile.find(receivedUser); + + if (receivedHistory > MAX_PASSWORD_HISTORY) { + LogError("Incorrect input param."); + return AUTH_PASSWD_API_ERROR_INPUT_PARAM; + } + + itPwd->second.setMaxHistorySize(receivedHistory); + itPwd->second.writeMemoryToFile(); + + return AUTH_PASSWD_API_SUCCESS; + } +} //namespace AuthPasswd diff --git a/src/server/service/password.cpp b/src/server/service/password.cpp new file mode 100644 index 0000000..4267539 --- /dev/null +++ b/src/server/service/password.cpp @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jooseong Lee <jooseong.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 + */ +/* + * @file password.cpp + * @author Zbigniew Jasinski (z.jasinski@samsung.com) + * @author Lukasz Kostyra (l.kostyra@partner.samsung.com) + * @author Jooseong Lee (jooseong.lee@samsung.com) + * @version 1.0 + * @brief Implementation of password service + */ + +#include <iostream> +#include <string> + +#include <dpl/log/log.h> +#include <dpl/serialization.h> + +#include <user-check.h> + +#include <password.h> + +#include <auth-passwd-error.h> +#include <password-exception.h> + +namespace AuthPasswd { + +namespace { +// Service may open more than one socket. +// These ID's will be assigned to sockets +// and will be used only by service. +// When new connection arrives, AcceptEvent +// will be generated with proper ID to inform +// service about input socket. +// +// Please note: SocketManager does not use it and +// does not check it in any way. +// +// If your service requires only one socket +// (uses only one socket labeled with smack) +// you may ignore this ID (just pass 0) +const InterfaceID SOCKET_ID_CHECK = 0; +const InterfaceID SOCKET_ID_SET = 1; +const InterfaceID SOCKET_ID_RESET = 2; +const InterfaceID SOCKET_ID_POLICY = 3; + +} // namespace anonymous + +GenericSocketService::ServiceDescriptionVector PasswordService::GetServiceDescription() +{ + return ServiceDescriptionVector { + {SERVICE_SOCKET_PASSWD_CHECK, "*", SOCKET_ID_CHECK}, + {SERVICE_SOCKET_PASSWD_SET, "*", SOCKET_ID_SET}, + {SERVICE_SOCKET_PASSWD_RESET, "*", SOCKET_ID_RESET}, + {SERVICE_SOCKET_PASSWD_POLICY, "*", SOCKET_ID_POLICY} + }; +} + +void PasswordService::Start() { + Create(); +} + +void PasswordService::Stop() { + Join(); +} + +void PasswordService::accept(const AcceptEvent &event) +{ + LogSecureDebug("Accept event. ConnectionID.sock: " << event.connectionID.sock + << " ConnectionID.counter: " << event.connectionID.counter + << " ServiceID: " << event.interfaceID); + + auto &info = m_connectionInfoMap[event.connectionID.counter]; + info.interfaceID = event.interfaceID; +} + +void PasswordService::write(const WriteEvent &event) +{ + LogSecureDebug("WriteEvent. ConnectionID: " << event.connectionID.sock << + " Size: " << event.size << " Left: " << event.left); + if (event.left == 0) + m_serviceManager->Close(event.connectionID); +} + +void PasswordService::process(const ReadEvent &event) +{ + LogSecureDebug("Read event for counter: " << event.connectionID.counter); + auto &info = m_connectionInfoMap[event.connectionID.counter]; + info.buffer.Push(event.rawBuffer); + + // We can get several requests in one package. + // Extract and process them all + while(processOne(event.connectionID, info.buffer, info.interfaceID)); +} + +void PasswordService::close(const CloseEvent &event) +{ + LogSecureDebug("CloseEvent. ConnectionID: " << event.connectionID.sock); + m_connectionInfoMap.erase(event.connectionID.counter); +} + +int PasswordService::processCheckFunctions(PasswordHdrs hdr, MessageBuffer& buffer, + const unsigned int cur_user, unsigned int &cur_att, + unsigned int &max_att, unsigned int &exp_time) +{ + int result = AUTH_PASSWD_API_ERROR_SERVER_ERROR; + + switch (hdr) { + case PasswordHdrs::HDR_CHK_PASSWD: { + unsigned int passwdType = 0; + std::string challenge; + Deserialization::Deserialize(buffer, passwdType); + Deserialization::Deserialize(buffer, challenge); + result = m_pwdManager.checkPassword(passwdType, challenge, cur_user, cur_att, max_att, + exp_time); + break; + } + + case PasswordHdrs::HDR_CHK_PASSWD_STATE: { + unsigned int passwdType = 0; + Deserialization::Deserialize(buffer, passwdType); + result = m_pwdManager.isPwdValid(passwdType, cur_user, cur_att, max_att, exp_time); + break; + } + + default: + LogError("Unknown msg header."); + Throw(Exception::IncorrectHeader); + } + + return result; +} + +int PasswordService::processSetFunctions(PasswordHdrs hdr, MessageBuffer& buffer, + const unsigned int cur_user, bool &isPwdReused) +{ + int result = AUTH_PASSWD_API_ERROR_SERVER_ERROR; + + switch(hdr) { + case PasswordHdrs::HDR_SET_PASSWD: { + std::string curPasswd, newPasswd; + unsigned int passwdType = 0, rec_att = 0, rec_days = 0, rec_history = 0; + Deserialization::Deserialize(buffer, passwdType); + Deserialization::Deserialize(buffer, curPasswd); + Deserialization::Deserialize(buffer, newPasswd); + /* TO DO: Check newPassword based on passwd policy. Get max att, expired date and histoy */ + result = m_pwdManager.setPassword(passwdType, curPasswd, newPasswd, cur_user, rec_att, + rec_days, rec_history); + break; + } + + case PasswordHdrs::HDR_SET_PASSWD_RECOVERY: { + std::string curRcvPasswd, newPasswd; + unsigned int rec_att = 0, rec_days = 0, rec_history = 0; + Deserialization::Deserialize(buffer, curRcvPasswd); + Deserialization::Deserialize(buffer, newPasswd); + /* TO DO: Check newPassword based on passwd policy. Get max att, expired date and histoy */ + + // Don't recovery password if MaxAttempt value is not infinite. + if (rec_days != PASSWORD_INFINITE_EXPIRATION_DAYS) + return AUTH_PASSWD_API_ERROR_RECOVERY_PASSWORD_RESTRICTED; + + result = m_pwdManager.setPasswordRecovery(curRcvPasswd, newPasswd, cur_user, rec_att, + rec_days, rec_history); + break; + } + + case PasswordHdrs::HDR_CHK_PASSWD_REUSED: { + unsigned int passwdType = 0; + std::string passwd; + Deserialization::Deserialize(buffer, passwdType); + Deserialization::Deserialize(buffer, passwd); + result = m_pwdManager.isPwdReused(passwdType, passwd, cur_user, isPwdReused); + break; + } + + default: + LogError("Unknown msg header."); + Throw(Exception::IncorrectHeader); + } + + return result; +} + +int PasswordService::processResetFunctions(PasswordHdrs hdr, MessageBuffer& buffer) +{ + int result = AUTH_PASSWD_API_ERROR_SERVER_ERROR; + + std::string newPasswd; + unsigned int passwdType = 0, rec_user = 0, rec_att = 0, rec_days = 0, rec_history = 0; + + switch(hdr) { + case PasswordHdrs::HDR_RST_PASSWD: + Deserialization::Deserialize(buffer, passwdType); + Deserialization::Deserialize(buffer, newPasswd); + Deserialization::Deserialize(buffer, rec_user); + + /* TO DO: Get max att, expired date and history */ + result = m_pwdManager.resetPassword(passwdType, newPasswd, rec_user, rec_att, rec_days, + rec_history); + break; + + default: + LogError("Unknown msg header."); + Throw(Exception::IncorrectHeader); + } + + return result; +} + +int PasswordService::processPolicyFunctions(PasswordHdrs hdr, MessageBuffer& buffer) +{ + int result = AUTH_PASSWD_API_SUCCESS; +/* + int result = AUTH_PASSWD_API_ERROR_SERVER_ERROR; + + policy_h *p_policy; + unsigned int rec_user = 0, rec_att = 0, rec_days = 0, rec_history = 0; + + swithch(hdr) { + case PasswordHdrs::HDR_SET_PASSWD_POLICY: { + Deserialization::Deserialize(buffer, p_policy); + + result = m_policyManager.setPolicy(p_policy); + + if(result == AUTH_PASSWD_API_SUCCESS) + m_pwdManager.setPasswordMaxAttempts(rec_user, rec_att); + m_pwdManager.setPasswordValidity(rec_user, rec_days); + m_pwdManager.setPasswordHistory(rec_user, rec_history); + } + break; + + default: + LogError("Unknown msg header."); + Throw(Exception::IncorrectHeader); + } +*/ + return result; +} + +bool PasswordService::processOne(const ConnectionID &conn, MessageBuffer &buffer, + InterfaceID interfaceID) +{ + LogSecureDebug("Iteration begin"); + + MessageBuffer sendBuffer; + + int retCode = AUTH_PASSWD_API_ERROR_SERVER_ERROR; + unsigned int cur_user = 0, cur_att = 0, max_att = 0, exp_time = 0; + bool isPwdReused; + + if (!buffer.Ready()) + return false; + + Try { //try..catch for MessageBuffer errors, closes connection when exception is thrown + int tempHdr; + Deserialization::Deserialize(buffer, tempHdr); + PasswordHdrs hdr = static_cast<PasswordHdrs>(tempHdr); + + 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)) + 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)) + retCode = AUTH_PASSWD_API_ERROR_NO_USER; + else + retCode = processSetFunctions(hdr, buffer, cur_user, isPwdReused); + break; + + case SOCKET_ID_RESET: + retCode = processResetFunctions(hdr, buffer); + break; + + case SOCKET_ID_POLICY: + retCode = processPolicyFunctions(hdr, buffer); + break; + + default: + LogError("Wrong interfaceID."); + Throw(Exception::IncorrectHeader); + } + } catch (PasswordException::Base &e) { + LogError("Password error: " << e.DumpToString()); + retCode = AUTH_PASSWD_API_ERROR_SERVER_ERROR; + } catch (std::exception &e) { + LogError("STD error: " << e.what()); + retCode = AUTH_PASSWD_API_ERROR_SERVER_ERROR; + } + + //everything is OK, send return code and extra data + Serialization::Serialize(sendBuffer, retCode); + + //Returning additional information should occur only when checking functions + //are called, and under certain return values + if (interfaceID == SOCKET_ID_CHECK) + { + switch(retCode) + { + case AUTH_PASSWD_API_ERROR_PASSWORD_MISMATCH: + case AUTH_PASSWD_API_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED: + case AUTH_PASSWD_API_ERROR_PASSWORD_EXPIRED: + case AUTH_PASSWD_API_SUCCESS: + Serialization::Serialize(sendBuffer, cur_att); + Serialization::Serialize(sendBuffer, max_att); + Serialization::Serialize(sendBuffer, exp_time); + break; + default: + break; + } + } else if (interfaceID == SOCKET_ID_SET) { + if (hdr == PasswordHdrs::HDR_CHK_PASSWD_REUSED && retCode == AUTH_PASSWD_API_SUCCESS) { + Serialization::Serialize(sendBuffer, (int)isPwdReused); + } + } + + m_serviceManager->Write(conn, sendBuffer.Pop()); + } Catch (MessageBuffer::Exception::Base) { + LogError("Broken protocol. Closing socket."); + m_serviceManager->Close(conn); + return false; + } Catch (PasswordService::Exception::Base) { + LogError("Incorrect message header. Closing socket."); + m_serviceManager->Close(conn); + return false; + } + + return true; +} + +} // namespace AuthPasswd + diff --git a/systemd/CMakeLists.txt b/systemd/CMakeLists.txt new file mode 100644 index 0000000..b4e46b4 --- /dev/null +++ b/systemd/CMakeLists.txt @@ -0,0 +1,11 @@ +INSTALL(FILES + ${CMAKE_SOURCE_DIR}/systemd/authentication-server.service + ${CMAKE_SOURCE_DIR}/systemd/authentication-server.target + ${CMAKE_SOURCE_DIR}/systemd/authentication-server-passwd-check.socket + ${CMAKE_SOURCE_DIR}/systemd/authentication-server-passwd-set.socket + ${CMAKE_SOURCE_DIR}/systemd/authentication-server-passwd-reset.socket + ${CMAKE_SOURCE_DIR}/systemd/authentication-server-passwd-policy.socket + DESTINATION + /usr/lib/systemd/system +) + diff --git a/systemd/authentication-server-passwd-check.socket b/systemd/authentication-server-passwd-check.socket new file mode 100644 index 0000000..d9bb7ec --- /dev/null +++ b/systemd/authentication-server-passwd-check.socket @@ -0,0 +1,14 @@ +[Socket] +ListenStream=/run/.authentication-server-api-passwd-check.sock +SocketMode=0777 +SmackLabelIPIn=* +SmackLabelIPOut=@ + +Service=authentication-server.service + +[Unit] +Wants=authentication-server.target +Before=authentication-server.target + +[Install] +WantedBy=sockets.target diff --git a/systemd/authentication-server-passwd-policy.socket b/systemd/authentication-server-passwd-policy.socket new file mode 100644 index 0000000..feb474c --- /dev/null +++ b/systemd/authentication-server-passwd-policy.socket @@ -0,0 +1,14 @@ +[Socket] +ListenStream=/run/.authentication-server-api-passwd-policy.sock +SocketMode=0777 +SmackLabelIPIn=* +SmackLabelIPOut=@ + +Service=authentication-server.service + +[Unit] +Wants=authentication-server.target +Before=authentication-server.target + +[Install] +WantedBy=sockets.target diff --git a/systemd/authentication-server-passwd-reset.socket b/systemd/authentication-server-passwd-reset.socket new file mode 100644 index 0000000..94b1c61 --- /dev/null +++ b/systemd/authentication-server-passwd-reset.socket @@ -0,0 +1,14 @@ +[Socket] +ListenStream=/run/.authentication-server-api-passwd-reset.sock +SocketMode=0777 +SmackLabelIPIn=* +SmackLabelIPOut=@ + +Service=authentication-server.service + +[Unit] +Wants=authentication-server.target +Before=authetication-server.target + +[Install] +WantedBy=sockets.target diff --git a/systemd/authentication-server-passwd-set.socket b/systemd/authentication-server-passwd-set.socket new file mode 100644 index 0000000..ff839bf --- /dev/null +++ b/systemd/authentication-server-passwd-set.socket @@ -0,0 +1,14 @@ +[Socket] +ListenStream=/run/.authentication-server-api-passwd-set.sock +SocketMode=0777 +SmackLabelIPIn=* +SmackLabelIPOut=@ + +Service=authentication-server.service + +[Unit] +Wants=authentication-server.target +Before=authentication-server.target + +[Install] +WantedBy=sockets.target diff --git a/systemd/authentication-server.service b/systemd/authentication-server.service new file mode 100644 index 0000000..92c3d97 --- /dev/null +++ b/systemd/authentication-server.service @@ -0,0 +1,13 @@ +[Unit] +Description=Start authentication server + +[Service] +Type=notify +ExecStart=/usr/bin/authentication-server +Sockets=authentication-server-passwd-check.socket +Sockets=authentication-server-passwd-set.socket +Sockets=authentication-server-passwd-reset.socket +Sockets=authentication-server-passwd-policy.socket + +[Install] +WantedBy=multi-user.target diff --git a/systemd/authentication-server.target b/systemd/authentication-server.target new file mode 100644 index 0000000..39d4861 --- /dev/null +++ b/systemd/authentication-server.target @@ -0,0 +1,4 @@ +[Unit] +Description=authentication server sockets +DefaultDependencies=true + |