upload tizen1.0 source
authorKim Kibum <kb0929.kim@samsung.com>
Sun, 29 Apr 2012 08:01:52 +0000 (17:01 +0900)
committerKim Kibum <kb0929.kim@samsung.com>
Sun, 29 Apr 2012 08:01:52 +0000 (17:01 +0900)
36 files changed:
AUTHORS [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0644]
LICENSE [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/docs [new file with mode: 0644]
debian/libsecurity-server-client-0.install.in [new file with mode: 0644]
debian/libsecurity-server-client-0.postinst [new file with mode: 0755]
debian/libsecurity-server-client-dev.install.in [new file with mode: 0644]
debian/rules [new file with mode: 0755]
debian/security-server.install.in [new file with mode: 0644]
debian/security-server.postinst [new file with mode: 0755]
include/security-server-comm.h [new file with mode: 0644]
include/security-server-common.h [new file with mode: 0644]
include/security-server-cookie.h [new file with mode: 0644]
include/security-server-password.h [new file with mode: 0644]
include/security-server-util.h [new file with mode: 0644]
include/security-server.h [new file with mode: 0644]
mw-list [new file with mode: 0644]
packaging/security-server.spec [new file with mode: 0644]
security-server.pc.in [new file with mode: 0644]
security-serverd [new file with mode: 0755]
src/client/security-server-client.c [new file with mode: 0644]
src/communication/security-server-comm.c [new file with mode: 0644]
src/server/security-server-cookie.c [new file with mode: 0644]
src/server/security-server-main.c [new file with mode: 0644]
src/server/security-server-password.c [new file with mode: 0644]
src/util/security-server-util-common.c [new file with mode: 0644]
src/util/security-server-util.c [new file with mode: 0644]
testcases/debug-util.c [new file with mode: 0644]
testcases/security_server_tc_client.c [new file with mode: 0644]
testcases/security_server_tc_password.c [new file with mode: 0644]
testcases/security_server_tc_pid_reuser.c [new file with mode: 0644]
testcases/security_server_tc_server.c [new file with mode: 0644]
testcases/test.h [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..a62936f
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Bumjin Im <bj.i@samsung.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2aabe26
--- /dev/null
@@ -0,0 +1,80 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(secrutiy-server-C)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(EXEC_PREFIX "\${prefix}")
+SET(LIBDIR "\${prefix}/lib")
+SET(INCLUDEDIR "\${prefix}/include")
+SET(VERSION_MAJOR 1)
+SET(VERSION ${VERSION_MAJOR}.0.1)
+
+#Verbose
+#SET(CMAKE_VERBOSE_MAKEFILE ON)
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(pkgs REQUIRED dlog openssl)
+
+FOREACH(flag ${pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(sec_svr_dir "./")
+SET(sec_svr_include_dir "./include")
+SET(sec_svr_src_dir "./src")
+SET(sec_svr_test_dir "./testcases")
+
+## Additional flag
+#SET(debug_type "-DSECURITY_SERVER_DEBUG_TO_CONSOLE")
+SET(debug_type "-DSECURITY_SERVER_DEBUG_DLOG")
+#SET(debug_type "")
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+
+###################################################################################################
+## for libsecurity-server-client.so (library)
+SET(libsecurity-server-client_SOURCES ${sec_svr_src_dir}/client/security-server-client.c ${sec_svr_src_dir}/communication/security-server-comm.c)
+SET(libsecurity-server-client_LDFLAGS " -module -avoid-version")
+SET(libsecurity-server-client_CFLAGS  " ${CFLAGS} -fPIC -I${sec_svr_include_dir} ${debug_type} -D_GNU_SOURCE ")
+#SET(libsecurity-server-client_LIBADD "")
+
+ADD_LIBRARY(security-server-client SHARED ${libsecurity-server-client_SOURCES})
+TARGET_LINK_LIBRARIES(security-server-client ${pkgs_LDFLAGS})
+SET_TARGET_PROPERTIES(security-server-client PROPERTIES SOVERSION ${VERSION_MAJOR})
+SET_TARGET_PROPERTIES(security-server-client PROPERTIES VERSION ${VERSION})
+SET_TARGET_PROPERTIES(security-server-client PROPERTIES COMPILE_FLAGS "${libsecurity-server-client_CFLAGS}")
+###################################################################################################
+
+###################################################################################################
+## for security-server (binary)
+SET(security-server_SOURCES ${sec_svr_src_dir}/server/security-server-main.c ${sec_svr_src_dir}/communication/security-server-comm.c ${sec_svr_src_dir}/server/security-server-cookie.c ${sec_svr_src_dir}/server/security-server-password.c ${sec_svr_src_dir}/util/security-server-util-common.c )
+SET(security-server_CFLAGS " -I/usr/include -I. -I${sec_svr_include_dir} ${debug_type} -D_GNU_SOURCE ")
+SET(security-server_LDFLAGS ${pkgs_LDFLAGS} -lpthread )
+
+ADD_EXECUTABLE(security-server ${security-server_SOURCES})
+TARGET_LINK_LIBRARIES(security-server ${pkgs_LDFLAGS})
+SET_TARGET_PROPERTIES(security-server PROPERTIES COMPILE_FLAGS "${security-server_CFLAGS}")
+####################################################################################################
+
+##FOR TEST METHOD ONLY. MUST BE DELETED ON RELEASE ############################################################
+## for security-server util (binary)
+SET(sec-svr-util_SOURCES ${sec_svr_src_dir}/util/security-server-util.c ${sec_svr_src_dir}/communication/security-server-comm.c ${sec_svr_src_dir}/util/security-server-util-common.c ${sec_svr_src_dir}/server/security-server-cookie.c)
+SET(sec-svr-util_CFLAGS " -I/usr/include -I. -I${sec_svr_include_dir} ${debug_type} -D_GNU_SOURCE ")
+SET(sec-svr-util_LDFLAGS ${pkgs_LDFLAGS})
+
+ADD_EXECUTABLE(sec-svr-util ${sec-svr-util_SOURCES})
+TARGET_LINK_LIBRARIES(sec-svr-util ${pkgs_LDFLAGS})
+SET_TARGET_PROPERTIES(sec-svr-util PROPERTIES COMPILE_FLAGS "${sec-svr-util_CFLAGS}")
+####################################################################################################
+
+CONFIGURE_FILE(security-server.pc.in security-server.pc @ONLY)
+
+INSTALL(TARGETS security-server-client DESTINATION lib)
+INSTALL(PROGRAMS ${CMAKE_BINARY_DIR}/security-server DESTINATION bin)
+INSTALL(PROGRAMS ${CMAKE_BINARY_DIR}/sec-svr-util DESTINATION bin)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/security-server.pc DESTINATION lib/pkgconfig)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/security-server.h DESTINATION include/security-server)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/mw-list DESTINATION share/security-server)
+INSTALL(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/security-serverd DESTINATION /etc/rc.d/init.d)
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..c0e0d97
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,205 @@
+
+Copyright (c) 2012 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 (c) 2012 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.
+
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..97c318a
--- /dev/null
@@ -0,0 +1,7 @@
+security-server (0.0.1-43) unstable; urgency=low
+
+  * Bug fixed: security_server_reset_pwd() fails when password sets for the first time.
+  * Git: pkgs/s/security-server
+  * Tag: security-server_0.0.1-43 
+
+ -- Bumjin <bj.im@samsung.com>  Wed, 18 Jan 2012 19:24:33 +0900
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..7ed6ff8
--- /dev/null
@@ -0,0 +1 @@
+5
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..7c3ee1b
--- /dev/null
@@ -0,0 +1,31 @@
+Source: security-server
+Priority: extra
+Maintainer: Bumjin Im <bj.im@samsung.com>, Kidong Kim <kd0228.kim@samsung.com>
+Build-Depends: debhelper (>= 5), autotools-dev, dlog-dev, libssl-dev, libattr1-dev
+Standards-Version: 3.7.2
+Section: base
+Homepage: N/A
+
+Package: libsecurity-server-client-dev
+Section: libs
+Architecture: any
+Depends: ${misc:Depends}, libsecurity-server-client-0 (= ${Source-Version}), dlog-dev
+Description: security server client library develpoment package
+
+Package: libsecurity-server-client-0
+Section: libs
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: security server client library package
+
+Package: security-server
+Section: base
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, libsecurity-server-client-0 (= ${Source-Version}), openssl
+Description: security server
+
+Package: security-server-dbg
+Section: debug
+Architecture: any
+Depends: ${misc:Depends}, security-server (= ${Source-Version})
+Description: debug package of security server source package
diff --git a/debian/docs b/debian/docs
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/debian/libsecurity-server-client-0.install.in b/debian/libsecurity-server-client-0.install.in
new file mode 100644 (file)
index 0000000..d34bd90
--- /dev/null
@@ -0,0 +1 @@
+usr/lib/*.so*
diff --git a/debian/libsecurity-server-client-0.postinst b/debian/libsecurity-server-client-0.postinst
new file mode 100755 (executable)
index 0000000..1a24852
--- /dev/null
@@ -0,0 +1 @@
+#!/bin/sh
diff --git a/debian/libsecurity-server-client-dev.install.in b/debian/libsecurity-server-client-dev.install.in
new file mode 100644 (file)
index 0000000..5658c40
--- /dev/null
@@ -0,0 +1,2 @@
+usr/include/security-server/security-server.h
+usr/lib/pkgconfig/security-server.pc
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..15799b4
--- /dev/null
@@ -0,0 +1,126 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+CFLAGS ?= -Wall -g
+CXXFLAGS ?=  -Wall -g
+LDFLAGS ?= 
+PREFIX ?= /usr
+DATADIR ?= /opt
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+       CFLAGS += -O0
+       CXXFLAGS += -O0
+else
+       CFLAGS += -O2
+       CXXFLAGS += -O2
+endif
+
+LDFLAGS += -Wl,--rpath=$(PREFIX)/lib -Wl,--as-needed
+
+configure: configure-stamp
+configure-stamp:
+       dh_testdir
+       # Add here commands to configure the package.
+       CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" cmake . -DCMAKE_INSTALL_PREFIX=$(PREFIX)
+
+       touch configure-stamp
+
+build: build-stamp
+
+build-stamp: configure-stamp 
+       dh_testdir
+
+       # Add here commands to compile the package.
+       $(MAKE)
+       #docbook-to-man debian/wavplayer.sgml > wavplayer.1
+
+       for f in `find $(CURDIR)/debian/ -name "*.in"`; do \
+               cat $$f > $${f%.in}; \
+               sed -i -e "s#@PREFIX@#$(PREFIX)#g" $${f%.in}; \
+               sed -i -e "s#@DATADIR@#$(DATADIR)#g" $${f%.in}; \
+       done
+
+
+       touch $@
+
+clean:
+       dh_testdir
+       dh_testroot
+       rm -f build-stamp configure-stamp
+
+       # Add here commands to clean up after the build process.
+       -$(MAKE) clean
+       rm -rf CMakeCache.txt
+       rm -rf CMakeFiles
+       rm -rf cmake_install.cmake
+       rm -rf Makefile
+       rm -rf install_manifest.txt
+       rm -rf *.so
+       rm -rf *.pc
+
+       for f in `find $(CURDIR)/debian/ -name "*.in"`; do \
+               rm -f $${f%.in}; \
+       done
+
+       dh_clean
+
+install: build
+       dh_testdir
+       dh_testroot
+       dh_clean -k 
+       dh_installdirs
+
+       # Add here commands to install the package into debian/wavplayer.
+       $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
+       mkdir -p $(CURDIR)/debian/tmp/etc/rc.d/rc3.d/
+       mkdir -p $(CURDIR)/debian/tmp/etc/rc.d/rc5.d/
+       ln -s ../init.d/security-serverd $(CURDIR)/debian/tmp/etc/rc.d/rc3.d/S25security-server
+       ln -s ../init.d/security-serverd $(CURDIR)/debian/tmp/etc/rc.d/rc5.d/S25security-server
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+       dh_testdir
+       dh_testroot
+       dh_installchangelogs 
+       dh_installdocs
+       dh_installexamples
+       dh_install --sourcedir=debian/tmp
+#      dh_installmenu
+#      dh_installdebconf       
+#      dh_installlogrotate
+#      dh_installemacsen
+#      dh_installpam
+#      dh_installmime
+#      dh_python
+#      dh_installinit
+#      dh_installcron
+#      dh_installinfo
+       dh_installman
+       dh_link
+#      dh_strip
+       dh_strip --dbg-package=security-server-dbg
+       dh_compress
+       dh_fixperms
+#      dh_perl
+       dh_makeshlibs
+       dh_installdeb
+       dh_shlibdeps
+       dh_gencontrol
+       dh_md5sums
+       dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
diff --git a/debian/security-server.install.in b/debian/security-server.install.in
new file mode 100644 (file)
index 0000000..9d6c7c4
--- /dev/null
@@ -0,0 +1,6 @@
+usr/bin/security-server
+etc/rc.d/rc3.d/S25security-server
+etc/rc.d/rc5.d/S25security-server
+etc/rc.d/init.d/security-serverd
+usr/share/security-server/mw-list
+/usr/bin/sec-svr-util
diff --git a/debian/security-server.postinst b/debian/security-server.postinst
new file mode 100755 (executable)
index 0000000..13f4793
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+
diff --git a/include/security-server-comm.h b/include/security-server-comm.h
new file mode 100644 (file)
index 0000000..c4ce939
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#ifndef SECURITY_SERVER_COMM_H
+#define SECURITY_SERVER_COMM_H
+
+/* Message */
+typedef struct
+{
+       unsigned char version;
+       unsigned char msg_id;
+       unsigned short msg_len;
+} basic_header;
+
+typedef struct
+{
+       basic_header basic_hdr;
+       unsigned char return_code;
+} response_header;
+
+/* Message Types */
+#define SECURITY_SERVER_MSG_TYPE_COOKIE_REQUEST                0x01
+#define SECURITY_SERVER_MSG_TYPE_COOKIE_RESPONSE       0x02
+#define SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_REQUEST       0x03
+#define SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_RESPONSE      0x04
+#define SECURITY_SERVER_MSG_TYPE_OBJECT_NAME_REQUEST   0x05
+#define SECURITY_SERVER_MSG_TYPE_OBJECT_NAME_RESPONSE  0x06
+#define SECURITY_SERVER_MSG_TYPE_GID_REQUEST           0x07
+#define SECURITY_SERVER_MSG_TYPE_GID_RESPONSE          0x08
+#define SECURITY_SERVER_MSG_TYPE_PID_REQUEST           0x09
+#define SECURITY_SERVER_MSG_TYPE_PID_RESPONSE          0x0a
+#define SECURITY_SERVER_MSG_TYPE_TOOL_REQUEST          0x0b
+#define SECURITY_SERVER_MSG_TYPE_TOOL_RESPONSE         0x0c
+#define SECURITY_SERVER_MSG_TYPE_VALID_PWD_REQUEST     0x0d
+#define SECURITY_SERVER_MSG_TYPE_VALID_PWD_RESPONSE    0x0e
+#define SECURITY_SERVER_MSG_TYPE_SET_PWD_REQUEST       0x0f
+#define SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE      0x10
+#define SECURITY_SERVER_MSG_TYPE_RESET_PWD_REQUEST     0x11
+#define SECURITY_SERVER_MSG_TYPE_RESET_PWD_RESPONSE    0x12
+#define SECURITY_SERVER_MSG_TYPE_CHK_PWD_REQUEST       0x13
+#define SECURITY_SERVER_MSG_TYPE_CHK_PWD_RESPONSE      0x14
+#define SECURITY_SERVER_MSG_TYPE_SET_PWD_HISTORY_REQUEST       0x15
+#define SECURITY_SERVER_MSG_TYPE_SET_PWD_HISTORY_RESPONSE      0x16
+#define SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE      0xff
+
+/* Return code */
+#define SECURITY_SERVER_RETURN_CODE_SUCCESS            0x00
+#define SECURITY_SERVER_RETURN_CODE_BAD_REQUEST                0x01
+#define SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED      0x02
+#define SECURITY_SERVER_RETURN_CODE_ACCESS_GRANTED     0x03
+#define SECURITY_SERVER_RETURN_CODE_ACCESS_DENIED      0x04
+#define SECURITY_SERVER_RETURN_CODE_NO_SUCH_OBJECT     0x05
+#define SECURITY_SERVER_RETURN_CODE_NO_SUCH_COOKIE     0x06
+#define SECURITY_SERVER_RETURN_CODE_NO_PASSWORD                0x07
+#define SECURITY_SERVER_RETURN_CODE_PASSWORD_EXIST             0x08
+#define SECURITY_SERVER_RETURN_CODE_PASSWORD_MISMATCH  0x09
+#define SECURITY_SERVER_RETURN_CODE_PASSWORD_MAX_ATTEMPTS_EXCEEDED     0x0a
+#define SECURITY_SERVER_RETURN_CODE_PASSWORD_EXPIRED   0x0b
+#define SECURITY_SERVER_RETURN_CODE_PASSWORD_REUSED    0x0c
+#define SECURITY_SERVER_RETURN_CODE_PASSWORD_RETRY_TIMER       0x0d
+#define SECURITY_SERVER_RETURN_CODE_SERVER_ERROR       0x0e
+
+int return_code_to_error_code(int ret_code);
+int create_new_socket(int *sockfd);
+int safe_server_sock_close(int client_sockfd);
+int connect_to_server(int *fd);
+int accept_client(int server_sockfd);
+int authenticate_client_application(int sockfd, int *pid, int *uid);
+int authenticate_client_middleware(int sockfd, int *pid);
+int authenticate_developer_shell(int sockfd);
+char *read_cmdline_from_proc(pid_t pid);
+int send_generic_response (int sockfd, unsigned char msgid, unsigned char return_code);
+int send_cookie(int sockfd, unsigned char *cookie);
+int send_object_name(int sockfd, char *obj);
+int send_gid(int sockfd, int gid);
+int send_cookie_request(int sock_fd);
+int send_gid_request(int sock_fd, const char* object);
+int send_object_name_request(int sock_fd, int gid);
+int send_privilege_check_request(int sock_fd, const char*cookie, int gid);
+int recv_get_gid_response(int sockfd, response_header *hdr, int *gid);
+int recv_get_object_name(int sockfd, response_header *hdr, char *object, int max_object_size);
+int recv_cookie(int sockfd, response_header *hdr, char *cookie);
+int recv_privilege_check_response(int sockfd, response_header *hdr);
+int recv_hdr(int client_sockfd, basic_header *basic_hdr);
+int recv_check_privilege_request(int sockfd, unsigned char *requested_cookie, int *requested_privilege);
+int send_pid_request(int sock_fd, const char*cookie);
+int recv_pid_response(int sockfd, response_header *hdr, int *pid);
+int recv_pid_request(int sockfd, unsigned char *requested_cookie);
+int send_pid(int sockfd, int pid);
+int send_launch_tool_request(int sock_fd, int argc, const char **argv);
+int recv_generic_response(int sockfd, response_header *hdr);
+int recv_launch_tool_request(int sockfd, int argc, char *argv[]);
+int recv_pwd_response(int sockfd, response_header *hdr, unsigned int *current_attempts, 
+       unsigned int *max_attempts, unsigned int *valid_days);
+int send_set_pwd_request(int sock_fd, const char*cur_pwd, const char*new_pwd, 
+       const unsigned int max_challenge, const unsigned int valid_period_in_days);
+int send_chk_pwd_request(int sock_fd, const char*challenge);
+int check_socket_poll(int sockfd, int event, int timeout);
+int free_argv(char **argv, int argc);
+
+#endif
diff --git a/include/security-server-common.h b/include/security-server-common.h
new file mode 100644 (file)
index 0000000..6ba0335
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#ifndef SECURITY_SERVER_COMMON_H
+#define SECURITY_SERVER_COMMON_H
+
+#include <sys/types.h>
+
+/* Definitions *********************************************************/
+/* Return value. Continuing from return value of the client header file */
+#define SECURITY_SERVER_SUCCESS                                0
+#define SECURITY_SERVER_ERROR_SOCKET                   -1
+#define SECURITY_SERVER_ERROR_BAD_REQUEST              -2
+#define SECURITY_SERVER_ERROR_BAD_RESPONSE             -3
+#define SECURITY_SERVER_ERROR_SEND_FAILED              -4
+#define SECURITY_SERVER_ERROR_RECV_FAILED              -5
+#define SECURITY_SERVER_ERROR_NO_SUCH_OBJECT           -6
+#define SECURITY_SERVER_ERROR_AUTHENTICATION_FAILED    -7
+#define SECURITY_SERVER_ERROR_INPUT_PARAM              -8
+#define SECURITY_SERVER_ERROR_BUFFER_TOO_SMALL         -9
+#define SECURITY_SERVER_ERROR_OUT_OF_MEMORY            -10
+#define SECURITY_SERVER_ERROR_ACCESS_DENIED            -11
+#define SECURITY_SERVER_ERROR_SERVER_ERROR             -12
+#define SECURITY_SERVER_ERROR_NO_SUCH_COOKIE           -13
+#define SECURITY_SERVER_ERROR_NO_PASSWORD              -14
+#define SECURITY_SERVER_ERROR_PASSWORD_EXIST           -15
+#define SECURITY_SERVER_ERROR_PASSWORD_MISMATCH                -16
+#define SECURITY_SERVER_ERROR_PASSWORD_RETRY_TIMER     -17
+#define SECURITY_SERVER_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED   -18
+#define SECURITY_SERVER_ERROR_PASSWORD_EXPIRED -19
+#define SECURITY_SERVER_ERROR_PASSWORD_REUSED  -20
+#define SECURITY_SERVER_ERROR_SOCKET_BIND              -21
+#define SECURITY_SERVER_ERROR_FILE_OPERATION           -22
+#define SECURITY_SERVER_ERROR_TIMEOUT                  -23
+#define SECURITY_SERVER_ERROR_POLL                     -24
+#define SECURITY_SERVER_ERROR_UNKNOWN                  -255
+
+/* Miscellaneous Definitions */
+#define SECURITY_SERVER_SOCK_PATH                      "/tmp/.security_server.sock"
+#define SECURITY_SERVER_DEFAULT_COOKIE_PATH            "/tmp/.security_server.coo"
+#define SECURITY_SERVER_DAEMON_PATH                    "/usr/bin/security-server"
+#define SECURITY_SERVER_COOKIE_LEN                     20
+#define SECURITY_SERVER_MIDDLEWARE_LIST_PATH           "/usr/share/security-server/mw-list"
+#define SECURITY_SERVER_MAX_OBJ_NAME                   30
+#define SECURITY_SERVER_MAX_PATH_LEN                   50
+#define SECURITY_SERVER_MSG_VERSION                    0x01
+#define SECURITY_SERVER_ACCEPT_TIMEOUT_MILISECOND      10000
+#define SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND      3000
+#define SECURITY_SERVER_DEVELOPER_UID                  5100
+#define SECURITY_SERVER_DEBUG_TOOL_PATH                        "/usr/bin/debug-util"
+#define SECURITY_SERVER_KILL_APP_PATH                  "/usr/bin/kill_app"
+#define SECURITY_SERVER_DATA_DIRECTORY_PATH            "/opt/data/security-server"
+#define SECURITY_SERVER_ATTEMPT_FILE_NAME      "attempts"
+#define SECURITY_SERVER_HISTORY_FILE_NAME      "history"
+#define SECURITY_SERVER_MAX_PASSWORD_LEN               32
+#define SECURITY_SERVER_HASHED_PWD_LEN                 32  /* SHA256 */
+#define SECURITY_SERVER_PASSWORD_RETRY_TIMEOUT_SECOND          1
+#define SECURITY_SERVER_MAX_PASSWORD_HISTORY   50
+#define SECURITY_SERVER_NUM_THREADS                    10
+
+/* API prefix */
+#ifndef SECURITY_SERVER_API
+#define SECURITY_SERVER_API    __attribute__((visibility("default")))
+#endif
+
+
+
+/* Data types *****************************************************************/
+/* Cookie List data type */
+typedef struct _cookie_list
+{
+       unsigned char   cookie[SECURITY_SERVER_COOKIE_LEN];     /* 20 bytes random Cookie */
+       int             path_len;                               /* Client process cmd line length */
+       int             permission_len;                         /* Client process permissions (aka group IDs) */
+       pid_t           pid;                                    /* Client process's PID */
+       char            *path;                                  /* Client process's cmd line string */
+       int             *permissions;                           /* Array of GID that the client process has */
+       struct _cookie_list     *prev;                          /* Next cookie list */
+       struct _cookie_list     *next;                          /* Previous cookie list */
+} cookie_list;
+
+
+/* Function prototypes ******************************************************/
+/* IPC */
+
+void printhex(const unsigned char *data, int size);
+
+/* Debug */
+#ifdef SECURITY_SERVER_DEBUG_TO_CONSOLE /* debug msg will be printed in console */
+#define SEC_SVR_DBG(FMT, ARG ...) fprintf(stderr, "[%s:%d] "FMT"\n", \
+               __FILE__, __LINE__, ##ARG)
+
+#elif SECURITY_SERVER_DEBUG_DLOG       /* debug msg will be printed by dlog daemon */
+#define LOG_TAG "SECURITY_SERVER"
+#include <dlog.h>
+#define SEC_SVR_DBG    SLOGD
+#else /* No debug output */
+#define SEC_SVR_DBG(FMT, ARG ...) {}
+#endif
+
+#endif
diff --git a/include/security-server-cookie.h b/include/security-server-cookie.h
new file mode 100644 (file)
index 0000000..373cab7
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#ifndef SECURITY_SERVER_COOKIE_H
+#define SECURITY_SERVER_COOKIE_H
+
+#include "security-server-common.h"
+
+int free_cookie_item(cookie_list *cookie);
+cookie_list *delete_cookie_item(cookie_list *cookie);
+cookie_list *search_existing_cookie(int pid, const cookie_list *c_list);
+cookie_list *search_cookie(const cookie_list *c_list, const unsigned char *cookie, int privilege);
+int generate_random_cookie(unsigned char *cookie, int size);
+cookie_list *create_cookie_item(int pid, cookie_list *c_list);
+cookie_list *create_default_cookie(void);
+cookie_list * garbage_collection(cookie_list *cookie);
+cookie_list *search_cookie_from_pid(cookie_list *c_list, int pid);
+void printhex(const unsigned char *data, int size);
+
+#endif
diff --git a/include/security-server-password.h b/include/security-server-password.h
new file mode 100644 (file)
index 0000000..a10e165
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#ifndef SECURITY_SERVER_PASSWORD_H
+#define SECURITY_SERVER_PASSWORD_H
+
+#include "security-server-common.h"
+#include "security-server-comm.h"
+
+int process_valid_pwd_request(int sockfd);
+int process_set_pwd_request(int sockfd);
+int process_reset_pwd_request(int sockfd);
+int process_reset_pwd_request(int sockfd);
+int process_chk_pwd_request(int sockfd);
+int init_try(void);
+
+#endif
diff --git a/include/security-server-util.h b/include/security-server-util.h
new file mode 100644 (file)
index 0000000..0a6cac3
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#ifndef SECURITY_SERVER_UTIL_H
+#define SECURITY_SERVER_UTIL_H
+
+/* Only for test */
+/* These msg type MUST BE REMOVED before release **************************/
+#define SECURITY_SERVER_MSG_TYPE_GET_ALL_COOKIES_REQUEST       0x51
+#define SECURITY_SERVER_MSG_TYPE_GET_ALL_COOKIES_RESPONSE      0x52
+#define SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_FROM_PID_REQUEST       0x53
+#define SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_RESPONSE       0x54
+#define SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_FROM_COOKIE_REQUEST    0x55
+/**********************************************************************/
+
+int util_process_all_cookie(int sockfd, cookie_list* list);
+int util_process_cookie_from_pid(int sockfd, cookie_list* list);
+int util_process_cookie_from_cookie(int sockfd, cookie_list* list);
+
+
+#endif
diff --git a/include/security-server.h b/include/security-server.h
new file mode 100644 (file)
index 0000000..f9862f9
--- /dev/null
@@ -0,0 +1,933 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#ifndef SECURITY_SERVER_H
+#define SECURITY_SERVER_H
+
+
+/**
+ * @file    security-server.h
+ * @version 1.0
+ * @brief   This file contains APIs of the Security Server
+*/
+
+/**
+ * @defgroup SecurityFW
+ * @{
+ *
+ * @defgroup SECURITY_SERVER Security Server
+ * @version  1.0
+ * @brief    Security Server client library functions
+ *
+*/
+
+/**
+ * @addtogroup SECURITY_SERVER
+ * @{
+*/
+
+/*
+ * ====================================================================================================
+ * <tt>
+ *
+ * Revision History:
+ *
+ *  -- Company Name -- | Modification Date | Description of Changes 
+ *  ----------------------------------------------------------------------- 
+ *   --- Samsung ------ | --- 2010-07-25 -- | First created
+ *
+ *    </tt>
+ */
+
+/**
+ * \name Return Codes
+ * exported by the foundation API.
+ * result codes begin with the start error code and extend into negative direction.
+ * @{
+*/
+#define SECURITY_SERVER_API_SUCCESS                    0
+/*! \brief   indicating the result of the one specific API is successful */
+#define SECURITY_SERVER_API_ERROR_SOCKET               -1
+
+/*! \brief   indicating the socket between client and Security Server has been failed  */
+#define SECURITY_SERVER_API_ERROR_BAD_REQUEST          -2
+
+/*! \brief   indicating the response from Security Server is malformed */
+#define SECURITY_SERVER_API_ERROR_BAD_RESPONSE         -3
+
+/*! \brief   indicating the transmitting request has been failed */
+#define SECURITY_SERVER_API_ERROR_SEND_FAILED          -4
+
+/*! \brief   indicating the receiving response has been failed */
+#define SECURITY_SERVER_API_ERROR_RECV_FAILED          -5
+
+/*! \brief   indicating requesting object is not exist */
+#define SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT       -6
+
+/*! \brief   indicating the authentication between client and server has been failed */
+#define SECURITY_SERVER_API_ERROR_AUTHENTICATION_FAILED        -7
+
+/*! \brief   indicating the API's input parameter is malformed */
+#define SECURITY_SERVER_API_ERROR_INPUT_PARAM          -8
+
+/*! \brief   indicating the output buffer size which is passed as parameter is too small */
+#define SECURITY_SERVER_API_ERROR_BUFFER_TOO_SMALL     -9
+
+/*! \brief   indicating system  is running out of memory state */
+#define SECURITY_SERVER_API_ERROR_OUT_OF_MEMORY                -10
+
+/*! \brief   indicating the access has been denied by Security Server */
+#define SECURITY_SERVER_API_ERROR_ACCESS_DENIED                -11
+
+/*! \brief   indicating Security Server has been failed for some reason */
+#define SECURITY_SERVER_API_ERROR_SERVER_ERROR         -12
+
+/*! \brief   indicating given cookie is not exist in the database  */
+#define SECURITY_SERVER_API_ERROR_NO_SUCH_COOKIE       -13
+
+/*! \brief   indicating there is no phone password set  */
+#define SECURITY_SERVER_API_ERROR_NO_PASSWORD          -14
+
+/*! \brief   indicating password exists in system  */
+#define SECURITY_SERVER_API_ERROR_PASSWORD_EXIST               -15
+
+/*! \brief   indicating password mismatch  */
+#define SECURITY_SERVER_API_ERROR_PASSWORD_MISMATCH    -16
+
+/*! \brief   indicating password retry timeout is not occurred yet  */
+#define SECURITY_SERVER_API_ERROR_PASSWORD_RETRY_TIMER -17
+
+/*! \brief   indicating password retry timeout is not occurred yet  */
+#define SECURITY_SERVER_API_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED       -18
+
+/*! \brief   indicating password retry timeout is not occurred yet  */
+#define SECURITY_SERVER_API_ERROR_PASSWORD_EXPIRED     -19
+
+/*! \brief   indicating password retry timeout is not occurred yet  */
+#define SECURITY_SERVER_API_ERROR_PASSWORD_REUSED      -20
+
+/*! \brief   indicating the error with unknown reason */
+#define SECURITY_SERVER_API_ERROR_UNKNOWN              -255
+/** @}*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+/**
+ * \par Description:
+ * Retreives Linux group ID from object name which is passed by parameter
+ *
+ * \par Purpose:
+ * This API may be used before security_server_check_privilege() API by middleware daemon to get group ID of a specific object.
+ *
+ * \par Typical use case:
+ * In middleware daemon, before checking privilege of a service the daemon need to know the GID of the service. This API support the functionality.
+ *
+ * \par Method of function operation:
+ * Opens /etc/group file and searches the object name as group name. If there is matching result, returns GID as integer
+ *
+ * \par Sync (or) Async:
+ * This is a Synchronous API.
+ *
+ * \par Important notes:
+ * - This API is only allowed to be called by pre-defined middleware daemon
+ *
+ * \param[in] object Name of the object which is kwnown by the caller.
+ *
+ * \return matching gid (positive integer) on success, or negative error code on error.
+ * 
+ * \par Prospective clients:
+ * Inhouse middleware
+ *
+ * \par Known issues/bugs:
+ * None
+ * 
+ * \pre None
+ * 
+ * \post None
+ *
+ * \see /etc/group,
+ * security_server_get_object_name(), security_server_check_privilege()
+ * 
+ * \remarks None
+ * 
+ * \par Sample code:
+ * \code
+ * #include <security-server.h>
+ * ...
+ * int retval;
+ *
+ * // You have to make sure that  the input param '*object' is defined in the platform
+ * retval = security_server_get_gid("telephony_makecall");
+ * if(retval < 0)
+ * {
+ *     printf("%s", "Error has occurred\n");
+ *     exit(0);
+ * }
+ * ...
+ * \endcode
+*/
+int security_server_get_gid(const char *object);
+
+
+
+/**
+ * \par Description:
+ * Retreives object name as mull terminated string from Linux group ID which is passed by parameter
+ *
+ * \par Purpose:
+ * This API may be used to get object name if the caller process only knows GID of the object.
+ *
+ * \par Typical use case:
+ * In middleware daemon, by some reason, need to know object name from the Linux group ID, then call this API to retrieve object name as string
+ *
+ * \par Method of function operation:
+ * Opens /etc/group file and searches matching gid. If there is matching result, returns name of the group as null terminated string
+ *
+ * \par Sync (or) Async:
+ * This is a Synchronous API.
+ *
+ * \par Important notes:
+ * - This API is only allowed to be called by pre-defined middleware daemon
+ *
+ * \param[in] gid Linux group ID which needed to be retrieved as object name.
+ * \param[out] object Place holder for matching object name for gid.
+ * \param[in] max_object_size Allocated byte size of parameter "object".
+ *
+ * \return 0 on success, or negative error code on error.
+ * 
+ * \par Prospective clients:
+ * Inhouse middleware.
+ *
+ * \par Known issues/bugs:
+ * None
+ * 
+ * \pre output parameter object must be malloced before calling this API not to make memory curruption
+ * 
+ * \post None
+ *
+ * \see /etc/group,
+ * security_server_get_gid()
+ * 
+ * \remarks None
+ * 
+ * \par Sample code:
+ * \code
+ * #include <security-server.h>
+ * ...
+ * int retval;
+ * char objectname[20];
+ * 
+ * // Call the API
+ * retval = security_server_get_object_name(6005, objectname, sizeof(objectname));
+ * if(retval < 0)
+ * {
+ *     printf("%s", "Error has occurred\n");
+ *     exit(0);
+ * }
+ * ...
+ * \endcode
+*/
+int security_server_get_object_name(gid_t gid, char *object, size_t max_object_size);
+
+
+
+/**
+ * \par Description:
+ * Request cookie to the Security Server. Cookie is a random bit stream which is used as ticket for user space object.
+ *
+ * \par Purpose:
+ * This API may be used by application and client middleware process to get access to middleware daemons.
+ *
+ * \par Typical use case:
+ * When an application process wants to get access to some middleware object, first call this API to get cookie value. Then it calls the service API to get service with the cookie value.
+ *
+ * \par Method of function operation:
+ * Caller process just send request message. Security Server checks proc file system to get list of gIDs the caller belongs, then create a random cookie and responds to caller.
+ *
+ * \par Sync (or) Async:
+ * This is a Synchronous API.
+ *
+ * \par Important notes:
+ * Cookie needs to be stored relatively secure.
+ *
+ * \param[out] cookie Place holder for cookie value.
+ * \param[in] max_cookie Allocated byte size of parameter "cookie".
+ *
+ * \return 0 on success, or negative error code on error.
+ * 
+ * \par Prospective clients:
+ * Any process
+ *
+ * \par Known issues/bugs:
+ * None
+ * 
+ * \pre output parameter cookie must be malloced before calling this API not to make memory curruption
+ * Size of the cookie can be retrieved by security_server_get_cookie_size() API.
+ * 
+ * \post None
+ *
+ * \see security_server_check_privilege(), security_server_get_cookie_size()
+ * 
+ * \remarks None
+ * 
+ * \par Sample code:
+ * \code
+ * #include <security-server.h>
+ * ...
+ * int retval;
+ * size_t cookie_size;
+ * cookie_size = security_server_get_cookie_size();
+ * unsigned char cookie[cookie_size];
+ *
+ * // Call the API
+ * retval = security_server_request_cookie(cookie, cookie_size);
+ * if(retval < 0)
+ * {
+ *     printf("%s", "Error has occurred\n");
+ *     exit(0);
+ * }
+ * ...
+ * \endcode
+*/
+int security_server_request_cookie(char *cookie, size_t max_cookie);
+
+
+
+/**
+ * \par Description:
+ * This API gets the cookie's byte size which is issued by Security Server.
+ *
+ * \par Purpose:
+ * This API may be used by application and middleware process to get size of cookie before getting and storing cookie value.
+ *
+ * \par Typical use case:
+ * When an application process wants to get access to some middleware object, first call this API to get cookie value. Then it calls the service API to get service with the cookie value.
+ *
+ * \par Method of function operation:
+ * This API just returns pre-defined integer value as cookie size.
+ *
+ * \par Sync (or) Async:
+ * This is a Synchronous API.
+ *
+ * \par Important notes:
+ * None
+ *
+ * \return Always returns byte size of the cookie. 
+ * 
+ * \par Prospective clients:
+ * Any process
+ *
+ * \par Known issues/bugs:
+ * None
+ * 
+ * \pre None
+ * 
+ * \post None
+ *
+ * \see security_server_request_cookie()
+
+ * \remarks None
+ * 
+ * \par Sample code:
+ * \code
+ * #include <security-server.h>
+ * ...
+ * int retval;
+ * size_t cookie_size;
+ *
+ * // API calling
+ * cookie_size = security_server_get_cookie_size();
+ * unsigned char cookie[cookie_size];
+ * 
+ * char objectname[20];
+ * retval = security_server_request_cookie(cookie, cookie_size);
+ * if(retval < 0)
+ * {
+ *     printf("%s", "Error has occurred\n");
+ *     exit(0);
+ * }
+ * ...
+ * \endcode
+*/
+int security_server_get_cookie_size(void);
+
+
+
+/**
+ * \par Description:
+ * This API checks the cookie is allowed to access to given object.
+ *
+ * \par Purpose:
+ * This API may be used by middleware process to ask the client application has privilege for the given object.
+ *
+ * \par Typical use case:
+ * When middleware server receives request message from client application process with cookie value, it calls this API to ask to Security Server that the client application has privilege to access the service. If yes, then the middleware daemon can continue service, if not, it can return error to client application.
+ *
+ * \par Method of function operation:
+ * When Security Server receives this request, it searches cookie database and check the cookie is there, if there is matching cookie, then it checks the cookie has the privilege. It returns success if there is match, if not, it returns error.
+ *
+ * \par Sync (or) Async:
+ * This is a Synchronous API.
+ *
+ * \par Important notes:
+ * Cookie value needs to be stored relatively secure\n
+ * Privilege should be pre-defined by Platform design.
+ *
+ * \param[in] cookie Received cookie value from client application
+ * \param[in] privilege Object group ID which the client application wants to access
+ *
+ * \return 0 on success, or negative error code on error.
+ * 
+ * \par Prospective clients:
+ * Only pre-defiend middleware daemons
+ *
+ * \par Known issues/bugs:
+ * None
+ * \pre None
+ * 
+ * \post None
+ *
+ * \see security_server_request_cookie(), security_server_get_gid(), security_server_get_cookie_size()
+ *  
+ * \remarks None
+ *  
+ * \par Sample code:
+ * \code
+ * #include <security-server.h>
+ * ...
+ * int retval;
+ * size_t cookie_size;
+ * int call_gid;
+ * cookie_size = security_server_get_cookie_size();
+ * unsigned char recved_cookie[cookie_size];
+ * 
+ * ... // Receiving request with cookie
+ *
+ * call_gid = security_server_get_gid("telephony_makecall");
+ * retval = security_server_check_privilege(recved_cookie, (gid_t)call_gid);
+ * if(retval < 0)
+ * {
+ *     if(retval == SECURITY_SERVER_API_ERROR_ACCESS_DENIED)
+ *     {
+ *             printf("%s", "access has been denied\n");
+ *             return;
+ *     }
+ *     printf("%s", "Error has occurred\n");
+ * }
+ * ...
+ *
+ * \endcode
+*/
+int security_server_check_privilege(const char *cookie, gid_t privilege);
+
+
+
+/**
+ * \par Description:
+ * This API searchs a cookie value and returns PID of the given cookie.
+ *
+ * \par Purpose:
+ * This API may be used by middleware process to ask the client application has privilege for the given object.
+ *
+ * \par Typical use case:
+ * In some cases, a middleware server wants to know PID of the application process. But if the middleware server uses non-direct IPC such as dbus, it's nearly impossible to know and guarantee peer PID. By using this API, the middleware server can retrieve a PID of the requesting process.
+ *
+ * \par Method of function operation:
+ * When Security Server receives this request, it searches cookie database and check the cookie is there, if there is matching cookie, then it returns corresponding PID for the cookie.
+ *
+ * \par Sync (or) Async:
+ * This is a Synchronous API.
+ *
+ * \par Important notes:
+ * Cookie value needs to be stored relatively secure\n
+ * This API is abled to be called only by pre-defined middleware servers.
+ *
+ * \param[in] cookie Received cookie value from client application. Cookie is not a null terminated human readable string. Make sure you're code doesn't have any string related process on the cookie.
+ *
+ * \return positive integer on success meaning the PID, 0 means the cookie is for root process, negative integer error code on error.
+ * 
+ * \par Prospective clients:
+ * Only pre-defiend middleware daemons
+ *
+ * \par Known issues/bugs:
+ * None
+ *
+ * \pre None
+ * 
+ * \post None
+ *
+ * \see security_server_request_cookie(), security_server_get_cookie_size()
+ *  
+ * \remarks the cookie is not a null terminated string. Cookie is a BINARY byte stream of such length which can be retrieved by security_server_get_cookie_size() API.
+ * Therefore, please do not use strcpy() family to process cookie value. You MUST use memcpy() function to process cookie value.
+ * You also have to know that the cookie value doesn't carry any null terminator. So you don't need to allocate 1 more byte of the cookie size.
+ *  
+ * \par Sample code:
+ * \code
+ * #include <security-server.h>
+ * ...
+ * int peerpid;
+ * size_t cookie_size;
+ * gid_t call_gid;
+ * cookie_size = security_server_get_cookie_size();
+ * unsigned char recved_cookie[cookie_size];
+ * 
+ * ... // Receiving request with cookie
+ *
+ * peerpid = security_server_get_cookie_pid(recved_cookie);
+ * if(peerpid < 0)
+ * {
+ *     printf("%s", "Error has occurred\n");
+ * }
+ * ...
+ *
+ * \endcode
+*/
+int security_server_get_cookie_pid(const char *cookie);
+
+
+
+/**
+ * \par Description:
+ * This API checks phone validity of password, to check existance, expiration, remaining attempts.
+ *
+ * \par Purpose:
+ * This API should be used by applications which needs phone password check. Caller application should behave properly after this API call.
+ *
+ * \par Typical use case:
+ * Lock screen can call this API before it shows unlock screen, if there is password, lock screen can show password input UI, if not, lock screen can show just unlock screen
+ *
+ * \par Method of function operation:
+ * Sends a validate request to security server and security server replies with password information.
+ *
+ * \par Sync (or) Async:
+ * This is a Synchronous API.
+ *
+ * \par Important notes:
+ * Password file should be stored safely. The password file will be stored by security server and only allowed itself to read/write, and data is will be securely hashed\n
+ *
+ * \param[out] current_attempts Number of password check missed attempts. 
+ * \param[out] max_attempts Number of maximum attempts that the password locks. 0 means infinite
+ * \param[out] valid_secs Remaining time in second which represents this password will be expired. 0xFFFFFFFF means infinite
+ *
+ * \return 0 if there is no password set, other negative integer error code on error.
+ * 
+ * \par Prospective clients:
+ * Applications which can unlock UI
+ *
+ * \par Known issues/bugs:
+ * None
+ *
+ * \pre None
+ * 
+ * \post None
+ *
+ * \see security_server_set_pwd(), security_server_chk_pwd()
+ *  
+ * \remarks If password file is currupted or accitentally deleted, this API may not synchronized with security-server, but security-server will check file status on next request.
+ *  
+ * \par Sample code:
+ * \code
+ * #include <security-server.h>
+ * ...
+ * int ret;
+ * unsigned int attempt, max_attempt, expire_sec;
+ *
+ * ret = security_server_is_pwd_valid(&attempt, &max_attempt, &expire_sec);
+ * if(is_pwd_set == SECURITY_SERVER_API_ERROR_NO_PASSWORD)
+ * {
+ *     printf("%s", "There is no password exists\n");
+ * }
+ * else if(is_pwd_set == SECURITY_SERVER_SUCCESS && expire_sec > 0 && attempt < max_attempts)
+ * {
+ *     printf("%s", "Password is valid by now\n");
+ * }
+ * else
+ * {
+ *     printf("%s", "Something wrong\n");
+ * }
+ * ...
+ *
+ * \endcode
+*/
+int security_server_is_pwd_valid(unsigned int *current_attempts, 
+                       unsigned int *max_attempts, 
+                       unsigned int *valid_secs);
+
+
+
+/**
+ * \par Description:
+ * This API sets phone password only if current password matches.
+ *
+ * \par Purpose:
+ * This API should be used by setting application when the user changes his/her phone password.
+ *
+ * \par Typical use case:
+ * Setting application calls this API to change phone password. Caller needs current password to grant the change.
+ *
+ * \par Method of function operation:
+ * Sends current password with new password to security-server, security-server checks current password and set new password to current only when current password is correct. Caller application can determine maximum number of attempts and expiration time in days
+ *
+ * \par Sync (or) Async:
+ * This is a Synchronous API.
+ *
+ * \par Important notes:
+ * There is retry timer on this API to limit replay attack. You will get error if you called this API too often.\n
+ *
+ * \param[in] cur_pwd Null terminated current password string. It can be NULL pointer if there is no password set yet - by calling security_server_is_pwd_empty()
+ * \param[in] new_pwd Null terminated new password string. It must not a NULL pointer.
+ * \param[in] max_challenge Maximum number of attempts that user can try to check the password without success in serial. 0 means infinity.
+ * \param[in] valid_period_in_days. Number of days that this password is valid. 0 means infinity
+ *
+ * \return 0 on seccuess, negative integer error code on error.
+ * 
+ * \par Prospective clients:
+ * Platform's THE ONLY setting application and some dedicated privileged processes
+ *
+ * \par Known issues/bugs:
+ * None
+ *
+ * \pre None
+ * 
+ * \post None
+ *
+ * \see security_server_is_pwd_valid(), security_server_chk_pwd(), security_server_reset_pwd()
+ *  
+ * \remarks Only setting application can call this API. The password file will be acces controlled and securely hashed. Security-server will remain previous password file to recover unexpected password file curruption.
+ * \remarks If current password exists and it's expired, or max attempts reached, you cannot call this API. You have to call security_server_reset_pwd() API.
+ *  
+ * \par Sample code:
+ * \code
+ * #include <security-server.h>
+ * ...
+ * int ret;
+ * unsigned int attempt, max_attempt, expire_sec;
+ *
+ * ret = security_server_is_pwd_valid(&attempt, &max_attempt, &expire_sec);
+ * if(is_pwd_set == SECURITY_SERVER_API_ERROR_NO_PASSWORD)
+ * {
+ *     printf("%s", "There is no password exists\n");
+ *     ret = security_server_set_pwd(NULL, "this_is_new_pwd", 20, 365);
+ *     if(ret != SECURITY_SERVER_API_SUCCESS)
+ *     {
+ *             printf("%s", "we have error\n");
+ *             ...
+ *     }
+ * }
+ * else if(is_pwd_set == SECURITY_SERVER_SUCCESS && expire_sec > 0 && attempt < max_attempts)
+ * {
+ *     printf("%s", "Password is valid by now\n");
+ *     ret = security_server_set_pwd("this_is_current_pwd", "this_is_new_pwd", 20, 365);
+ *     if(ret != SECURITY_SERVER_API_SUCCESS)
+ *     {
+ *             printf("%s", "we have error\n");
+ *             ...
+ *     }
+ * }
+ * else
+ * {
+ *     printf("%s", "Something wrong\n");
+ * }
+ * ...
+ *
+ * \endcode
+*/
+int security_server_set_pwd(const char *cur_pwd,
+                       const char *new_pwd, 
+                       const unsigned int max_challenge, 
+                       const unsigned int valid_period_in_days);
+
+
+
+/**
+ * \par Description:
+ * This API sets phone password only if current password is invalid or user forgot the password.
+ *
+ * \par Purpose:
+ * This API should be used by setting application or dedicated processes when the user changes his/her phone password.
+ *
+ * \par Typical use case:
+ * User forgots the password. He calls emergency manager(auto or manual)  for reset password. Emergency manager calls this API and reset phone password.
+ *
+ * \par Method of function operation:
+ * Resetting phone password with input string without any matching current password.
+ *
+ * \par Sync (or) Async:
+ * This is a Synchronous API.
+ *
+ * \par Important notes:
+ * There is retry timer on this API to limit replay attack. You will get error if you called this API too often.\n
+ *
+ * \param[in] new_pwd Null terminated new password string. It must not a NULL pointer.
+ * \param[in] max_challenge Maximum number of attempts that user can try to check the password without success in serial. 0 means infinity.
+ * \param[in] valid_period_in_days. Number of days that this password is valid. 0 means infinity
+ *
+ * \return 0 on seccuess, negative integer error code on error.
+ * 
+ * \par Prospective clients:
+ * Platform's THE ONLY setting application and some dedicated privileged processes
+ *
+ * \par Known issues/bugs:
+ * None
+ *
+ * \pre None
+ * 
+ * \post None
+ *
+ * \see security_server_is_pwd_valid(), security_server_chk_pwd(), security_server_set_pwd()
+ *  
+ * \remarks Only dedicated applications can call this API. The password file will be acces controlled and securely hashed. Security-server will remain previous password file to recover unexpected password file curruption.
+ *  
+ * \par Sample code:
+ * \code
+ * #include <security-server.h>
+ * ...
+ * int ret;
+ * unsigned int attempt, max_attempt, expire_sec;
+ *
+ *     ret = security_server_set_pwd("this_is_new_pwd", 20, 365);
+ *     if(retval != SECURITY_SERVER_API_SUCCESS)
+ *     {
+ *             printf("%s", "we have error\n");
+ *             ...
+ *     }
+ * ...
+ *
+ * \endcode
+*/
+int security_server_reset_pwd(const char *new_pwd,
+                       const unsigned int max_challenge, 
+                       const unsigned int valid_period_in_days);
+
+/**
+ * \par Description:
+ * This API compares stored phone password with challenged input value.
+ *
+ * \par Purpose:
+ * This API should be used by applications which has phone UI lock capability.
+ *
+ * \par Typical use case:
+ * Lock screen calls this API after user typed phone password and pressed okay.
+ *
+ * \par Method of function operation:
+ * Sends challenged password to security-server, security-server compares hashed current password and hashed challenged password.
+ *
+ * \par Sync (or) Async:
+ * This is a Synchronous API.
+ *
+ * \par Important notes:
+ * There is retry timer on this API to limit replay attack. You will get error if you called this API too often.\n
+ *
+ * \param[in] challenge Null terminated challenged password string. It must not a NULL pointer.
+ * \param[out] current_attempts Number of password check missed attempts. 
+ * \param[out] max_attempts Number of maximum attempts that the password locks. 0 means infinite
+ * \param[out] valid_secs Remaining time in second which represents this password will be expired. 0xFFFFFFFF means infinite
+ *
+ * \return 0 on seccuess, negative integer error code on error.
+ * 
+ * \par Prospective clients:
+ * Applications which has phone UI lock feature.
+ *
+ * \par Known issues/bugs:
+ * None
+ *
+ * \pre None
+ * 
+ * \post None
+ *
+ * \see security_server_is_pwd_valid(), security_server_set_pwd()
+ *  
+ * \remarks The password file will be acces controlled and securely hashed. Security-server will remain previous password file to recover unexpected password file curruption.
+ *  
+ * \par Sample code:
+ * \code
+ * #include <security-server.h>
+ * ...
+ * int retval;
+ * unsigned int attempt, max_attempt, expire_sec; 
+ *
+ * retval = security_server_chk_pwd("is_this_password", &attmpt, &max_attempt, &expire_sec);
+ * if(retval == SECURITY_SERVER_API_ERROR_PASSWORD_MISMATCH)
+ * {
+ *     printf("%s", "Oh you typed wrong password\n");
+ *     ...
+ * }
+ * else if(retval == SECURITY_SERVER_API_SUCCESS)
+ * {
+ *     printf("%s", "You remember your password.\n");
+ *     ...
+ * }
+ * ...
+ *
+ * \endcode
+*/
+int security_server_chk_pwd(const char *challenge, 
+                       unsigned int *current_attempt, 
+                       unsigned int *max_attempt, 
+                       unsigned int *valid_secs);
+
+
+/**
+ * \par Description:
+ * This API set the number of password history which should be maintained. Once this number set, user cannot reuse recent number of passwords which is described in this history value
+ *
+ * \par Purpose:
+ * This API should be used only by dedicated process in the platform.
+ *
+ * \par Typical use case:
+ * Enterprise manager calls this API when the enterprise wants to enforce harder password policy.
+ *
+ * \par Method of function operation:
+ * When enterprise manager (MDM) is trying to change the security policy for phone password, it calls this API background to change the history policy.
+ *
+ * \par Sync (or) Async:
+ * This is a Synchronous API.
+ *
+ * \par Important notes:
+ * There is retry timer on this API to limit replay attack. You will get error if you called this API too often.\n
+ *
+ * \param[in] number_of_history Number of history to be checked when user tries to change password. Maximum is currently 50
+ *
+ * \return 0 on seccuess, negative integer error code on error.
+ * 
+ * \par Prospective clients:
+ * MDM client, Enterprise manager.
+ *
+ * \par Known issues/bugs:
+ * None
+ *
+ * \pre None
+ * 
+ * \post None
+ *
+ * \see security_server_set_pwd()
+ *  
+ * \remarks The password file will be acces controlled and securely hashed. Security-server will remain previous password file to recover unexpected password file curruption.
+ *  
+ * \par Sample code:
+ * \code
+ * #include <security-server.h>
+ * ...
+ * int retval;
+ *
+ * ret = security_server_set_pwd_history(100);
+ *     if(ret != SECURITY_SERVER_API_SUCCESS)
+ *     {
+ *             printf("%s", "You have error\n");
+ *             ...
+ *     }
+ * ...
+ *
+ * \endcode
+*/
+int security_server_set_pwd_history(int number_of_history);
+
+
+
+/**
+ * \par Description:
+ * This API launches /usr/bin/debug-util as root privilege.
+ *
+ * \par Purpose:
+ * This API will be used only by SDK with developer privilege to launch debugging tool to debug as the developing applicaion's privilege.
+ *
+ * \par Typical use case:
+ * During appliation development, SDK opens a shell to install, launch, and debug the developing application. But the shell will not have any privilege to control platform. Therefore we need a special utility to manage debugging environement as same privilege level of the application. If this API is called, security server will launch the debug utility as root privilege and the utility will drop its privilege same as developing application
+ *
+ *
+ * \par Method of function operation:
+ * When Security Server receives this request, it checks uid of the client, and launches /usr/bin/debug-util with given arguements.
+ *
+ * \par Sync (or) Async:
+ * This is a Synchronous API.
+ *
+ * \par Important notes:
+ * Caller process of this API must be owned by developer user.\n
+ * The caller process will be pre-defined.
+ * /usr/bin/debug-util itself must be omitted in the argv. Security server will put this as first argv in the execution procedure
+ *
+ * \param[in] argc Number of arguements.
+ * 
+ * \param[in] argv Arguements
+ *
+ * \return 0 on success, negative integer error code on error.
+ * 
+ * \par Prospective clients:
+ * Only pre-defiend debugging utility.
+ *
+ * \par Known issues/bugs:
+ * None
+ *
+ * \pre None
+ * 
+ * \post None
+ *
+ * \see None
+ *  
+ * \remarks Calling this API, you have to put argv[1] of the debug-util as argv[0] of this API. Security server will put argv[0] automatically
+ *  
+ * \par Sample code:
+ * \code
+ * #include <security-server.h>
+ * #define DEVELOPER_UID 5500
+ *
+ * int main(int argc, char **argv)
+ * {
+ *     int my_uid, ret;
+ *     uid = getuid();
+ *     if(uid != DEVELOPER_UID)
+ *     {
+ *             // You must be developer user
+ *             exit(1);
+ *     }
+ *
+ *     ret = security_server_launch_debug_tool(argc -1, argv++)
+ *     if(ret != SECURITY_SERVER_SUCCESS)
+ *     {
+ *             // Some error occurred
+ *             exit(1);
+ *     }
+ *     ...
+ * }
+ *
+ * \endcode
+*/
+int security_server_launch_debug_tool(int argc, const char **argv);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+*/
+
+/**
+ * @}
+*/
+
+#endif 
diff --git a/mw-list b/mw-list
new file mode 100644 (file)
index 0000000..9bfa0b0
--- /dev/null
+++ b/mw-list
@@ -0,0 +1,13 @@
+/usr/bin/telephony-server
+/usr/bin/ss-server
+/usr/bin/dnet
+/usr/bin/msg-server
+/usr/bin/alarm-server
+/usr/bin/dnet
+/usr/bin/audio-session-mgr-server
+/usr/bin/lbs_server
+/usr/bin/power_manager
+/usr/bin/system_server
+/opt/home/root/security_server_tc_server
+/usr/bin/sec-svr-util
+
diff --git a/packaging/security-server.spec b/packaging/security-server.spec
new file mode 100644 (file)
index 0000000..7519aae
--- /dev/null
@@ -0,0 +1,81 @@
+Name:       security-server
+Summary:    Security server
+Version: 0.0.1
+Release:    37
+Group:      TO_BE/FILLED_IN
+License:    Apache 2.0
+Source0:    %{name}-%{version}.tar.gz
+BuildRequires:  cmake
+BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(openssl)
+BuildRequires:  libattr-devel
+
+%description
+Security server package
+
+%package -n libsecurity-server-client
+Summary:    Security server (client)
+Group:      Development/Libraries
+Requires:   %{name} = %{version}-%{release}
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description -n libsecurity-server-client
+Security server package (client)
+
+%package -n libsecurity-server-client-devel
+Summary:    Security server (client-devel)
+Group:      Development/Libraries
+Requires:   libsecurity-server-client = %{version}-%{release}
+
+%description -n libsecurity-server-client-devel
+Security server package (client-devel)
+
+
+%prep
+%setup -q
+
+%build
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix}
+
+
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+
+%post
+mkdir -p /etc/rc.d/rc3.d
+mkdir -p /etc/rc.d/rc5.d
+ln -s /etc/rc.d/init.d/security-serverd /etc/rc.d/rc3.d/S25security-server
+ln -s /etc/rc.d/init.d/security-serverd /etc/rc.d/rc5.d/S25security-server
+
+%postun
+rm -f /etc/rc.d/rc3.d/S25security-server
+rm -f /etc/rc.d/rc5.d/S25security-server
+
+%post -n libsecurity-server-client -p /sbin/ldconfig
+
+%postun -n libsecurity-server-client -p /sbin/ldconfig
+
+
+%files
+%defattr(-,root,root,-)
+/etc/rc.d/init.d/security-serverd
+/usr/bin/security-server
+/usr/bin/sec-svr-util
+/usr/share/security-server/mw-list
+
+
+%files -n libsecurity-server-client
+%defattr(-,root,root,-)
+/usr/lib/libsecurity-server-client.so.*
+
+%files -n libsecurity-server-client-devel
+%defattr(-,root,root,-)
+/usr/lib/libsecurity-server-client.so
+/usr/include/security-server/security-server.h
+/usr/lib/pkgconfig/security-server.pc
+
diff --git a/security-server.pc.in b/security-server.pc.in
new file mode 100644 (file)
index 0000000..fab62e9
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+libdir=@LIBDIR@
+includedir=@INCLUDEDIR@
+
+Name: security-server 
+Description: Security Server Package
+Version: @VERSION@
+#Requires: openssl
+Libs: -L${libdir} -lsecurity-server-client
+Cflags: -I${includedir}/security-server 
diff --git a/security-serverd b/security-serverd
new file mode 100755 (executable)
index 0000000..48fbefc
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+# start secure-storage server
+/usr/bin/security-server &
diff --git a/src/client/security-server-client.c b/src/client/security-server-client.c
new file mode 100644 (file)
index 0000000..8e78d18
--- /dev/null
@@ -0,0 +1,828 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "security-server.h"
+#include "security-server-common.h"
+#include "security-server-comm.h"
+
+#if 0
+void printhex(unsigned char *data, int size)
+{
+       int i;
+       for(i=0;i<size;i++)
+       {
+               if(data[i] < 0xF)
+                       printf("0");
+
+               printf("%X ", data[i]);
+               if(((i+1) % 16) == 0 && i != 0)
+                       printf("\n");
+       }
+       printf("\n");
+}
+
+
+char *read_cmdline_from_proc(pid_t pid)
+{
+       int memsize = 32;
+       char path[32];
+       char *cmdline = NULL;
+
+       snprintf(path, sizeof(path), "/proc/%d/exe", pid);
+
+       cmdline = malloc(32);
+       if(cmdline == NULL)
+       {
+               SEC_SVR_DBG("%s", "Out of memory");
+               goto error;
+       }
+
+       while(1)
+       {
+               bzero(cmdline, memsize);
+               /* readlink() may have security hole in normal symbolic link. *
+                * But this link is located at proc fs that only kernel can change */
+               readlink(path, cmdline, memsize);       /* FlawFinder: ignore */
+SEC_SVR_DBG("pid: %d, cmdline: %s", pid, cmdline);
+
+               /* Check it's truncated */              
+               if(cmdline[memsize -1] != 0)
+               {
+                       cmdline = (char *)realloc(cmdline, sizeof(char) * (memsize + 32));
+                       memsize += 32;
+                       if(cmdline == NULL)
+                       {
+                               SEC_SVR_DBG("%s", "Out of memory");
+                               goto error;             
+                       }
+               }
+               else
+                       break;
+       }
+
+error:
+       return cmdline;
+}
+#endif
+
+
+/* We may need to filter error code */
+int convert_to_public_error_code(int err_code)
+{
+       /* Do we need this? */
+       return err_code;
+}
+
+
+
+       SECURITY_SERVER_API
+int security_server_get_gid(const char *object)
+{
+       int sockfd = -1, retval, gid;
+       response_header hdr;
+
+       if(object == NULL)
+       {
+               SEC_SVR_DBG("%s", "Client: object is null or object is too big");
+               retval = SECURITY_SERVER_API_ERROR_INPUT_PARAM;
+               goto error;
+       }
+       if( strlen(object) > SECURITY_SERVER_MAX_OBJ_NAME )
+       {
+               SEC_SVR_DBG("%s", "object is null or object is too big");
+               retval = SECURITY_SERVER_API_ERROR_INPUT_PARAM;
+               goto error;
+       }
+
+       if(strlen(object) == 0)
+       {
+               SEC_SVR_DBG("Client: object is is empty");
+               retval = SECURITY_SERVER_API_ERROR_INPUT_PARAM;
+               goto error;
+       }
+
+       SEC_SVR_DBG("%s", "Client: security_server_get_gid() is called");
+       retval = connect_to_server(&sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Connection failed: %d", retval);
+               goto error;
+       }
+       SEC_SVR_DBG("%s", "Client: Security server has been connected");
+
+       /* make request packet and send to server*/
+       retval = send_gid_request(sockfd, object);
+       SEC_SVR_DBG("%s", "Client: gid request has been sent");
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Send gid request failed: %d", retval);
+               goto error;
+       }
+
+       /* Receive response */
+       retval = recv_get_gid_response(sockfd, &hdr, &gid);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("Client: Receive response failed: %d", retval);
+               goto error;
+       }
+       SEC_SVR_DBG("%s", "Client: get gid response has been received");
+
+       if(hdr.basic_hdr.msg_id != SECURITY_SERVER_MSG_TYPE_GID_RESPONSE)       /* Wrong response */
+       {
+               if(hdr.basic_hdr.msg_id == SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE)
+               {
+                       /* There must be some error */
+                       SEC_SVR_DBG("Client: It'll be an error. return code:%d", hdr.return_code);
+                       retval = return_code_to_error_code(hdr.return_code);
+                       goto error;
+               }
+               else
+               {
+                       /* Something wrong with response */
+                       SEC_SVR_DBG("Client: Something wrong with response:%d", hdr.basic_hdr.msg_id);
+                       retval = SECURITY_SERVER_ERROR_BAD_RESPONSE;
+                       goto error;
+               }
+       }
+
+       SEC_SVR_DBG("received gid is %d", gid);
+       retval = gid;
+
+error:
+       if(sockfd > 0)
+               close(sockfd);
+       /* If error happened */
+       if(retval < 0)
+               retval = convert_to_public_error_code(retval);
+
+       return retval;
+}
+
+
+
+
+       SECURITY_SERVER_API
+int security_server_get_object_name(gid_t gid, char *object, size_t max_object_size)
+{
+       int sockfd = -1, retval;
+       response_header hdr;
+
+       if(object == NULL)
+       {
+               retval = SECURITY_SERVER_ERROR_INPUT_PARAM;
+               goto error;
+       }
+
+       retval = connect_to_server(&sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Client: connect to server failed: %d", retval);
+               goto error;
+       }
+
+       /* make request packet */
+       retval = send_object_name_request(sockfd, gid);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Client: cannot send request: %d", retval);
+               goto error;
+       }
+
+       retval = recv_get_object_name(sockfd, &hdr, object, max_object_size);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("Client: Receive response failed: %d", retval);
+               goto error;
+       }
+
+       if(hdr.basic_hdr.msg_id != SECURITY_SERVER_MSG_TYPE_OBJECT_NAME_RESPONSE)       /* Wrong response */
+       {
+               if(hdr.basic_hdr.msg_id == SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE)
+               {
+                       /* There must be some error */
+                       SEC_SVR_DBG("Client: There is error on response: return code:%d", hdr.basic_hdr.msg_id);
+                       retval = return_code_to_error_code(hdr.return_code);
+               }
+               else
+               {
+                       /* Something wrong with response */
+                       SEC_SVR_DBG("Client: Some unexpected error happene: return code:%d", hdr.basic_hdr.msg_id);
+                       retval = SECURITY_SERVER_ERROR_BAD_RESPONSE;
+               }
+               goto error;
+       }
+
+error:
+       if(sockfd > 0)
+               close(sockfd);
+
+       retval = convert_to_public_error_code(retval);
+       return retval;
+}
+
+
+
+       SECURITY_SERVER_API
+int security_server_request_cookie(char *cookie, size_t max_cookie)
+{
+       int sockfd = -1, retval;
+       response_header hdr;
+
+       if(cookie == NULL)
+       {
+               retval = SECURITY_SERVER_ERROR_INPUT_PARAM;
+               goto error;
+       }
+       if(max_cookie < SECURITY_SERVER_COOKIE_LEN)
+       {
+               retval = SECURITY_SERVER_ERROR_BUFFER_TOO_SMALL;
+               goto error;
+       }
+
+       SEC_SVR_DBG("%s", "Client: security_server_request_cookie() is called");
+       retval = connect_to_server(&sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("%s", "Client: connection failed");
+               goto error;
+       }
+
+       /* make request packet */
+       retval = send_cookie_request(sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Client: send cookie failed: %d", retval);
+               goto error;
+       }
+       SEC_SVR_DBG("%s", "Client: cookie request sent");
+       retval = recv_cookie(sockfd, &hdr, cookie);
+
+       if(hdr.basic_hdr.msg_id != SECURITY_SERVER_MSG_TYPE_COOKIE_RESPONSE)    /* Wrong response */
+       {
+               if(hdr.basic_hdr.msg_id == SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE)
+               {
+                       /* There must be some error */
+                       SEC_SVR_DBG("Client ERROR: There is an error on response. return code:%d", hdr.return_code);
+                       retval = return_code_to_error_code(hdr.return_code);
+               }
+               else
+               {
+                       /* Something wrong with response */
+                       SEC_SVR_DBG("Client ERROR: Unexpected error occurred:%d", retval);
+                       retval = SECURITY_SERVER_ERROR_BAD_RESPONSE;
+               }
+               goto error;
+       }
+       SEC_SVR_DBG("%s", "Client: cookie received");
+
+error:
+       if(sockfd > 0)
+               close(sockfd);
+
+       retval = convert_to_public_error_code(retval);
+       return retval;
+}
+
+
+
+
+
+       SECURITY_SERVER_API
+int security_server_check_privilege(const char *cookie, gid_t privilege)
+{
+       int sockfd = -1, retval;
+       response_header hdr;
+
+       if(cookie == NULL)
+       {
+               retval = SECURITY_SERVER_ERROR_INPUT_PARAM;
+               goto error;
+       }
+
+       retval = connect_to_server(&sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               goto error;
+       }
+
+       /* make request packet */
+       retval = send_privilege_check_request(sockfd, cookie, privilege);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Send failed: %d", retval);
+               goto error;
+       }
+
+       retval = recv_privilege_check_response(sockfd, &hdr);
+
+       retval = return_code_to_error_code(hdr.return_code);
+       if(hdr.basic_hdr.msg_id != SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_RESPONSE)   /* Wrong response */
+       {
+               if(hdr.basic_hdr.msg_id == SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE)
+               {
+                       /* There must be some error */
+                       SEC_SVR_DBG("Client: Error has been received. return code:%d", hdr.return_code);
+               }
+               else
+               {
+                       /* Something wrong with response */
+                       SEC_SVR_DBG("Client ERROR: Unexpected error occurred:%d", retval);
+                       retval = SECURITY_SERVER_ERROR_BAD_RESPONSE;
+               }
+               goto error;
+       }
+
+error:
+       if(sockfd > 0)
+               close(sockfd);
+
+       retval = convert_to_public_error_code(retval);
+       return retval;
+}
+
+
+
+
+
+       SECURITY_SERVER_API
+int security_server_get_cookie_size(void)
+{
+       return SECURITY_SERVER_COOKIE_LEN;
+}
+
+
+
+       SECURITY_SERVER_API
+int security_server_get_cookie_pid(const char *cookie)
+{
+       int sockfd = -1, retval, pid = -1;
+       response_header hdr;
+
+       if(cookie == NULL)
+       {
+               retval = SECURITY_SERVER_ERROR_INPUT_PARAM;
+               goto error;
+       }
+
+       retval = connect_to_server(&sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               goto error;
+       }
+
+       /* make request packet */
+       retval = send_pid_request(sockfd, cookie);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Client: Send failed: %d", retval);
+               goto error;
+       }
+
+       retval = recv_pid_response(sockfd, &hdr, &pid);
+
+       retval = return_code_to_error_code(hdr.return_code);
+       if(hdr.basic_hdr.msg_id != SECURITY_SERVER_MSG_TYPE_PID_RESPONSE)       /* Wrong response */
+       {
+               if(hdr.basic_hdr.msg_id == SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE)
+               {
+                       /* There must be some error */
+                       SEC_SVR_DBG("Client: Error has been received. return code:%d", hdr.return_code);
+               }
+               else
+               {
+                       /* Something wrong with response */
+                       SEC_SVR_DBG("Client ERROR: Unexpected error occurred:%d", retval);
+                       retval = SECURITY_SERVER_ERROR_BAD_RESPONSE;
+               }
+               goto error;
+       }
+       if(hdr.return_code == SECURITY_SERVER_RETURN_CODE_NO_SUCH_COOKIE)
+       {
+               SEC_SVR_DBG("%s"," Client: There is no such cookie exist");
+       }
+
+error:
+       if(sockfd > 0)
+               close(sockfd);
+
+       retval = convert_to_public_error_code(retval);
+       if(retval == 0)
+               return pid;
+
+       return retval;
+}
+
+
+
+       SECURITY_SERVER_API
+int security_server_launch_debug_tool(int argc, const char **argv)
+{
+       int sockfd = -1, retval;
+       response_header hdr;
+
+       if(argc < 1 || argv == NULL || argv[0] == NULL)
+       {
+               retval = SECURITY_SERVER_ERROR_INPUT_PARAM;
+               goto error;
+       }
+
+       if(argc == 1)
+       {
+               if(strcmp(argv[0], SECURITY_SERVER_KILL_APP_PATH) != 0)
+               {
+                       retval = SECURITY_SERVER_ERROR_INPUT_PARAM;
+                       goto error;
+               }
+       }
+
+       /* Check the caller is developer shell */
+       retval = getuid();
+       if(retval != SECURITY_SERVER_DEVELOPER_UID)
+       {
+               SEC_SVR_DBG("Client: It's not allowed to call this API by uid %d", retval);
+               retval = SECURITY_SERVER_ERROR_AUTHENTICATION_FAILED;
+               goto error;
+       }
+
+       retval = connect_to_server(&sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               goto error;
+       }
+
+       /* make request packet */
+       retval = send_launch_tool_request(sockfd, argc, argv);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Client: Send failed: %d", retval);
+               goto error;
+       }
+
+       retval = recv_generic_response(sockfd, &hdr);
+
+       retval = return_code_to_error_code(hdr.return_code);
+       if(hdr.basic_hdr.msg_id != SECURITY_SERVER_MSG_TYPE_TOOL_RESPONSE)      /* Wrong response */
+       {
+               if(hdr.basic_hdr.msg_id == SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE)
+               {
+                       /* There must be some error */
+                       SEC_SVR_DBG("Client: Error has been received. return code:%d", hdr.return_code);
+               }
+               else
+               {
+                       /* Something wrong with response */
+                       SEC_SVR_DBG("Client ERROR: Unexpected error occurred:%d", retval);
+                       retval = SECURITY_SERVER_ERROR_BAD_RESPONSE;
+               }
+               goto error;
+       }
+
+error:
+       if(sockfd > 0)
+               close(sockfd);
+
+       retval = convert_to_public_error_code(retval);
+       return retval;
+}
+
+
+
+       SECURITY_SERVER_API
+int security_server_is_pwd_valid(unsigned int *current_attempts, 
+       unsigned int *max_attempts, 
+       unsigned int *valid_secs)
+{
+       int sockfd = -1, retval = SECURITY_SERVER_ERROR_UNKNOWN;
+       response_header hdr;
+
+       if(current_attempts == NULL || max_attempts == NULL ||valid_secs == NULL)
+       {
+               retval = SECURITY_SERVER_ERROR_INPUT_PARAM;
+               goto error;
+       }
+
+       /* Authenticate self that is setting app  goes here */
+       /* 1st, check cmdline which is setting app */
+       /* 2nd, check /proc/self/attr/current for the SMACK label */
+
+       retval = connect_to_server(&sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               goto error;
+       }
+
+       /* make request packet */
+       retval = send_valid_pwd_request(sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Client: Send failed: %d", retval);
+               goto error;
+       }
+
+       retval = recv_pwd_response(sockfd, &hdr, current_attempts, max_attempts, valid_secs);
+
+       retval = return_code_to_error_code(hdr.return_code);
+       if(hdr.basic_hdr.msg_id != SECURITY_SERVER_MSG_TYPE_VALID_PWD_RESPONSE) /* Wrong response */
+       {
+               if(hdr.basic_hdr.msg_id == SECURITY_SERVER_MSG_TYPE_VALID_PWD_RESPONSE)
+               {
+                       /* There must be some error */
+                       SEC_SVR_DBG("Client: Error has been received. return code:%d", hdr.return_code);
+               }
+               else
+               {
+                       /* Something wrong with response */
+                       SEC_SVR_DBG("Client ERROR: Unexpected error occurred:%d", retval);
+                       retval = SECURITY_SERVER_ERROR_BAD_RESPONSE;
+               }
+               goto error;
+       }
+error:
+       if(sockfd > 0)
+               close(sockfd);
+
+       retval = convert_to_public_error_code(retval);
+       return retval;
+}
+
+
+
+       SECURITY_SERVER_API
+int security_server_set_pwd(const char *cur_pwd,
+                       const char *new_pwd, 
+                       const unsigned int max_challenge, 
+                       const unsigned int valid_period_in_days)
+{
+       int sockfd = -1, retval;
+       response_header hdr;
+
+       if(new_pwd == NULL || strlen(new_pwd) > SECURITY_SERVER_MAX_PASSWORD_LEN)
+       {
+               retval = SECURITY_SERVER_ERROR_INPUT_PARAM;
+               goto error;
+       }
+
+       /* Authenticate self that is setting app  goes here */
+       /* 1st, check cmdline which is setting app */
+       /* 2nd, check /proc/self/attr/current for the SMACK label */
+
+       retval = connect_to_server(&sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               goto error;
+       }
+
+       /* make request packet */
+       retval = send_set_pwd_request(sockfd, cur_pwd, new_pwd, max_challenge, valid_period_in_days);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Client: Send failed: %d", retval);
+               goto error;
+       }
+
+       retval = recv_generic_response(sockfd, &hdr);
+
+       retval = return_code_to_error_code(hdr.return_code);
+       if(hdr.basic_hdr.msg_id != SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE)   /* Wrong response */
+       {
+               if(hdr.basic_hdr.msg_id == SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE)
+               {
+                       /* There must be some error */
+                       SEC_SVR_DBG("Client: Error has been received. return code:%d", hdr.return_code);
+               }
+               else
+               {
+                       /* Something wrong with response */
+                       SEC_SVR_DBG("Client ERROR: Unexpected error occurred:%d", retval);
+                       retval = SECURITY_SERVER_ERROR_BAD_RESPONSE;
+               }
+               goto error;
+       }
+error:
+       if(sockfd > 0)
+               close(sockfd);
+
+       retval = convert_to_public_error_code(retval);
+       return retval;
+}
+
+
+
+       SECURITY_SERVER_API
+int security_server_reset_pwd(const char *new_pwd,
+                       const unsigned int max_challenge, 
+                       const unsigned int valid_period_in_days)
+{
+       int sockfd = -1, retval;
+       response_header hdr;
+
+       if(new_pwd == NULL || strlen(new_pwd) > SECURITY_SERVER_MAX_PASSWORD_LEN)
+       {
+               retval = SECURITY_SERVER_ERROR_INPUT_PARAM;
+               goto error;
+       }
+
+       /* Authenticate self that is setting app  goes here */
+       /* 1st, check cmdline which is setting app */
+       /* 2nd, check /proc/self/attr/current for the SMACK label */
+
+       retval = connect_to_server(&sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               goto error;
+       }
+
+       /* make request packet */
+       retval = send_reset_pwd_request(sockfd, new_pwd, max_challenge, valid_period_in_days);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Client: Send failed: %d", retval);
+               goto error;
+       }
+
+       retval = recv_generic_response(sockfd, &hdr);
+
+       retval = return_code_to_error_code(hdr.return_code);
+       if(hdr.basic_hdr.msg_id != SECURITY_SERVER_MSG_TYPE_RESET_PWD_RESPONSE) /* Wrong response */
+       {
+               if(hdr.basic_hdr.msg_id == SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE)
+               {
+                       /* There must be some error */
+                       SEC_SVR_DBG("Client: Error has been received. return code:%d", hdr.return_code);
+               }
+               else
+               {
+                       /* Something wrong with response */
+                       SEC_SVR_DBG("Client ERROR: Unexpected error occurred:%d", retval);
+                       retval = SECURITY_SERVER_ERROR_BAD_RESPONSE;
+               }
+               goto error;
+       }
+error:
+       if(sockfd > 0)
+               close(sockfd);
+
+       retval = convert_to_public_error_code(retval);
+       return retval;
+}
+
+
+
+       SECURITY_SERVER_API
+int security_server_chk_pwd(const char *challenge, 
+       unsigned int *current_attempt,
+       unsigned int *max_attempts,
+       unsigned int *valid_secs)
+{
+       int sockfd = -1, retval;
+       response_header hdr;
+
+       if(challenge == NULL || strlen(challenge) > SECURITY_SERVER_MAX_PASSWORD_LEN
+               || current_attempt == NULL || max_attempts == NULL || valid_secs == NULL)
+       {
+               retval = SECURITY_SERVER_ERROR_INPUT_PARAM;
+               goto error;
+       }
+
+       /* Authenticate self goes here */
+
+       retval = connect_to_server(&sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               goto error;
+       }
+
+       /* make request packet */
+       retval = send_chk_pwd_request(sockfd, challenge);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Client: Send failed: %d", retval);
+               goto error;
+       }
+
+       retval = recv_pwd_response(sockfd, &hdr, current_attempt, max_attempts, valid_secs);
+
+       retval = return_code_to_error_code(hdr.return_code);
+       if(hdr.basic_hdr.msg_id != SECURITY_SERVER_MSG_TYPE_CHK_PWD_RESPONSE)   /* Wrong response */
+       {
+               if(hdr.basic_hdr.msg_id == SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE)
+               {
+                       /* There must be some error */
+                       SEC_SVR_DBG("Client: Error has been received. return code:%d", hdr.return_code);
+               }
+               else
+               {
+                       /* Something wrong with response */
+                       SEC_SVR_DBG("Client ERROR: Unexpected error occurred:%d", retval);
+                       retval = SECURITY_SERVER_ERROR_BAD_RESPONSE;
+               }
+               goto error;
+       }
+error:
+       if(sockfd > 0)
+               close(sockfd);
+
+       retval = convert_to_public_error_code(retval);
+       return retval;
+}
+
+       SECURITY_SERVER_API
+int security_server_set_pwd_history(int number_of_history)
+{
+       int sockfd = -1, retval;
+       response_header hdr;
+
+       if(number_of_history > SECURITY_SERVER_MAX_PASSWORD_HISTORY || number_of_history < 0)
+               return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
+
+       /* Authenticate self that is setting app  goes here */
+       /* 1st, check cmdline which is setting app */
+       /* 2nd, check /proc/self/attr/current for the SMACK label */
+
+       retval = connect_to_server(&sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               goto error;
+       }
+
+       /* make request packet */
+       retval = send_set_pwd_history_request(sockfd, number_of_history);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Client: Send failed: %d", retval);
+               goto error;
+       }
+       retval = recv_generic_response(sockfd, &hdr);
+
+       retval = return_code_to_error_code(hdr.return_code);
+       if(hdr.basic_hdr.msg_id != SECURITY_SERVER_MSG_TYPE_SET_PWD_HISTORY_RESPONSE)   /* Wrong response */
+       {
+               if(hdr.basic_hdr.msg_id == SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE)
+               {
+                       /* There must be some error */
+                       SEC_SVR_DBG("Client: Error has been received. return code:%d", hdr.return_code);
+               }
+               else
+               {
+                       /* Something wrong with response */
+                       SEC_SVR_DBG("Client ERROR: Unexpected error occurred:%d", retval);
+                       retval = SECURITY_SERVER_ERROR_BAD_RESPONSE;
+               }
+               goto error;
+       }
+error:
+       if(sockfd > 0)
+               close(sockfd);
+
+       retval = convert_to_public_error_code(retval);
+       return retval;
+}
diff --git a/src/communication/security-server-comm.c b/src/communication/security-server-comm.c
new file mode 100644 (file)
index 0000000..689681d
--- /dev/null
@@ -0,0 +1,2058 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+#include <fcntl.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "security-server-common.h"
+#include "security-server-comm.h"
+
+void printhex(const unsigned char *data, int size)
+{
+       int i;
+       for(i=0;i<size;i++)
+       {
+               if(data[i] < 0xF)
+                       printf("0");
+
+               printf("%X ", data[i]);
+               if(((i+1) % 16) == 0 && i != 0)
+                       printf("\n");
+       }
+       printf("\n");
+}
+
+char *read_cmdline_from_proc(pid_t pid)
+{
+       int memsize = 32;
+       char path[32];
+       char *cmdline = NULL, *tempptr = NULL;
+       FILE *fp = NULL;
+
+       snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
+
+       fp = fopen(path, "r");
+       if(fp == NULL)
+       {
+               SEC_SVR_DBG("Cannot open cmdline on pid[%d]", pid);
+               return NULL;
+       }
+
+       cmdline = malloc(32);
+       if(cmdline == NULL)
+       {
+               SEC_SVR_DBG("%s", "Out of memory");
+               fclose(fp);
+               return NULL;
+       }
+
+       bzero(cmdline, memsize);
+       if(fgets(cmdline, 32, fp) == NULL)
+       {
+               SEC_SVR_DBG("%s", "Cannot read cmdline");
+               free(cmdline);
+               fclose(fp);
+               return NULL;
+       }
+
+       while(cmdline[memsize -2] != 0)
+       {
+               cmdline[memsize -1] = (char) fgetc(fp);
+               tempptr = realloc(cmdline, memsize + 32);
+               if(tempptr == NULL)
+               {
+                       fclose(fp);
+                       SEC_SVR_DBG("%s", "Out of memory");
+                       return NULL;
+               }
+               cmdline = tempptr;
+               bzero(cmdline + memsize, 32);
+               fgets(cmdline + memsize, 32, fp);
+               memsize += 32;
+       }
+
+       if(fp != NULL)
+               fclose(fp);
+       return cmdline;
+}
+
+/* Return code in packet is positive integer *
+ * We need to convert them to error code which are negative integer */
+int return_code_to_error_code(int ret_code)
+{
+       int ret;
+       switch(ret_code)
+       {
+               case SECURITY_SERVER_RETURN_CODE_SUCCESS:
+               case SECURITY_SERVER_RETURN_CODE_ACCESS_GRANTED:
+                       ret = SECURITY_SERVER_SUCCESS;
+                       break;
+               case SECURITY_SERVER_RETURN_CODE_BAD_REQUEST:
+                       ret = SECURITY_SERVER_ERROR_BAD_REQUEST;
+                       break;
+               case SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED:
+                       ret = SECURITY_SERVER_ERROR_AUTHENTICATION_FAILED;
+                       break;
+               case SECURITY_SERVER_RETURN_CODE_ACCESS_DENIED:
+                       ret = SECURITY_SERVER_ERROR_ACCESS_DENIED;
+                       break;
+               case SECURITY_SERVER_RETURN_CODE_NO_SUCH_OBJECT:
+                       ret = SECURITY_SERVER_ERROR_NO_SUCH_OBJECT;
+                       break;
+               case SECURITY_SERVER_RETURN_CODE_SERVER_ERROR:
+                       ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
+                       break;
+               case SECURITY_SERVER_RETURN_CODE_NO_SUCH_COOKIE:
+                       ret = SECURITY_SERVER_ERROR_NO_SUCH_COOKIE;
+                       break;
+               case SECURITY_SERVER_RETURN_CODE_NO_PASSWORD:
+                       ret = SECURITY_SERVER_ERROR_NO_PASSWORD;
+                       break;
+               case SECURITY_SERVER_RETURN_CODE_PASSWORD_EXIST:
+                       ret = SECURITY_SERVER_ERROR_PASSWORD_EXIST;
+                       break;
+               case SECURITY_SERVER_RETURN_CODE_PASSWORD_MISMATCH:
+                       ret = SECURITY_SERVER_ERROR_PASSWORD_MISMATCH;
+                       break;
+               case SECURITY_SERVER_RETURN_CODE_PASSWORD_RETRY_TIMER:
+                       ret = SECURITY_SERVER_ERROR_PASSWORD_RETRY_TIMER;
+                       break;
+               case SECURITY_SERVER_RETURN_CODE_PASSWORD_EXPIRED:
+                       ret = SECURITY_SERVER_ERROR_PASSWORD_EXPIRED;
+                       break;
+               case SECURITY_SERVER_RETURN_CODE_PASSWORD_MAX_ATTEMPTS_EXCEEDED:
+                       ret = SECURITY_SERVER_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED;
+                       break;
+               case SECURITY_SERVER_RETURN_CODE_PASSWORD_REUSED:
+                       ret = SECURITY_SERVER_ERROR_PASSWORD_REUSED;
+                       break;
+               default:
+                       ret = SECURITY_SERVER_ERROR_UNKNOWN;
+                       break;
+       }
+       return ret;
+}
+
+int check_socket_poll(int sockfd, int event, int timeout)
+{
+       struct pollfd poll_fd[1];
+       int retval = SECURITY_SERVER_ERROR_POLL;
+
+       poll_fd[0].fd = sockfd;
+       poll_fd[0].events = event;
+       retval = poll(poll_fd, 1, timeout);
+       if(retval < 0)
+       {
+               SEC_SVR_DBG("poll() error. errno=%d", errno);
+               if(errno != EINTR)
+                       return SECURITY_SERVER_ERROR_POLL;
+               else
+               {
+                       /* Chile process has been closed. Not poll() problem. Call it once again */ 
+                       return check_socket_poll(sockfd, event, timeout);
+               }
+       }
+
+       /* Timed out */
+       if(retval == 0)
+       {
+               return SECURITY_SERVER_ERROR_TIMEOUT;
+       }
+
+       if(poll_fd[0].revents != event)
+       {
+               SEC_SVR_DBG("Something wrong on the peer socket. event=0x%x", poll_fd[0].revents);
+               return SECURITY_SERVER_ERROR_POLL;
+       }
+       return SECURITY_SERVER_SUCCESS;
+}
+
+int safe_server_sock_close(int client_sockfd)
+{
+       struct pollfd poll_fd[1];
+       int retval;
+       retval = SECURITY_SERVER_ERROR_POLL;
+       poll_fd[0].fd = client_sockfd;
+       poll_fd[0].events = POLLRDHUP;
+       retval = poll(poll_fd, 1, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       SEC_SVR_DBG("%s", "Server: Closing server socket");
+       close(client_sockfd);
+       return SECURITY_SERVER_SUCCESS;
+}
+
+/* Create a Unix domain socket and bind */
+int create_new_socket(int *sockfd)
+{
+       int retval = 0, localsockfd = 0, flags;
+       struct sockaddr_un serveraddr;
+       mode_t sock_mode;
+
+       /* Deleted garbage Unix domain socket file */
+       remove(SECURITY_SERVER_SOCK_PATH);
+
+       /* Create Unix domain socket */
+       if((localsockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0 )
+       {
+               retval = SECURITY_SERVER_ERROR_SOCKET;
+               localsockfd = -1;
+               SEC_SVR_DBG("%s", "Socket creation failed");
+               goto error;
+       }
+
+       if((fsetxattr(localsockfd, "security.SMACK64IPOUT", "@", 2, 0)) < 0)
+       {
+               SEC_SVR_DBG("%s", "SMACK labeling failed");
+               if(errno != EOPNOTSUPP)
+               {
+                       retval = SECURITY_SERVER_ERROR_SOCKET;
+                       localsockfd = -1;
+                       goto error;
+               }
+       }
+       if((fsetxattr(localsockfd, "security.SMACK64IPIN", "*", 2, 0)) < 0)
+       {       SEC_SVR_DBG("%s", "SMACK labeling failed");
+               if(errno != EOPNOTSUPP)
+               {
+                       retval = SECURITY_SERVER_ERROR_SOCKET;
+                       localsockfd = -1;
+                       goto error;
+               }
+       }
+
+       /* Make socket as non blocking */
+       if((flags = fcntl(localsockfd, F_GETFL, 0)) < 0 || 
+                       fcntl(localsockfd, F_SETFL, flags | O_NONBLOCK) < 0)
+       {
+               retval = SECURITY_SERVER_ERROR_SOCKET;
+               close(localsockfd);
+               localsockfd = -1;
+               SEC_SVR_DBG("%s", "Cannot go to nonblocking mode");
+               goto error;
+       }
+
+       bzero (&serveraddr, sizeof(serveraddr));
+       serveraddr.sun_family = AF_UNIX;
+       strncpy(serveraddr.sun_path, SECURITY_SERVER_SOCK_PATH, 
+                       strlen(SECURITY_SERVER_SOCK_PATH));
+       serveraddr.sun_path[strlen(SECURITY_SERVER_SOCK_PATH)] = 0;
+
+       /* Bind the socket */
+       if((bind(localsockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
+       {
+               retval = SECURITY_SERVER_ERROR_SOCKET_BIND;
+               SEC_SVR_DBG("%s", "Cannot bind");
+               close(localsockfd);
+               localsockfd = -1;
+               goto error;
+       }
+       
+
+       /* Change permission to accept all processes that has different uID/gID */
+       sock_mode = (S_IRWXU | S_IRWXG | S_IRWXO);
+       /* Flawfinder hits this chmod function as level 5 CRITICAL as race condition flaw *
+        * Flawfinder recommends to user fchmod insted of chmod
+        * But, fchmod doesn't work on socket file so there is no other choice at this point */
+       if(chmod(SECURITY_SERVER_SOCK_PATH, sock_mode) < 0)             /* Flawfinder: ignore */
+       {
+               SEC_SVR_DBG("%s", "chmod() error");
+               retval = SECURITY_SERVER_ERROR_SOCKET;
+               close(localsockfd);
+               localsockfd = -1;
+               goto error;
+       }
+
+       retval = SECURITY_SERVER_SUCCESS;
+
+error:
+       *sockfd = localsockfd;
+       return retval;
+}
+
+/* Authenticate peer that it's really security server.
+ * Check UID that is root
+ */
+int authenticate_server(int sockfd)
+{
+       int retval;
+       struct ucred cr;
+       unsigned int cl = sizeof(cr);
+/*     char *cmdline = NULL;*/
+
+       /* get socket peer credential */
+       if(getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cr, &cl) != 0)
+       {
+               retval = SECURITY_SERVER_ERROR_SOCKET;
+               SEC_SVR_DBG("%s", "getsockopt() failed");
+               goto error;
+       }
+
+       /* Security server must run as root */
+       if(cr.uid != 0)
+       {
+               retval = SECURITY_SERVER_ERROR_AUTHENTICATION_FAILED;
+               SEC_SVR_DBG("Peer is not root: uid=%d", cr.uid);
+               goto error;
+       }
+       else
+               retval = SECURITY_SERVER_SUCCESS;
+
+       /* Read command line of the PID from proc fs */
+       /* This is commented out because non root process cannot read link of /proc/pid/exe */
+/*     cmdline = read_cmdline_from_proc(cr.pid);
+
+       if(strcmp(cmdline, SECURITY_SERVER_DAEMON_PATH) != 0)
+       {
+               retval = SECURITY_SERVER_ERROR_AUTHENTICATION_FAILED;
+               SEC_SVR_DBG("Cmdline is different. auth failed. cmdline=%s", cmdline);
+       }
+       else
+       {
+               retval = SECURITY_SERVER_SUCCESS;
+               SEC_SVR_DBG("Server authenticatd. %s, sockfd=%d", cmdline, sockfd);
+       }
+*/
+error:
+/*     if(cmdline != NULL)
+               free(cmdline);
+*/
+       return retval;
+}
+
+/* Create a socket and connect to Security Server */
+int connect_to_server(int *fd)
+{
+       struct sockaddr_un clientaddr;
+       int client_len = 0, localsockfd, ret, flags;
+       *fd = -1;
+
+       /* Create a socket */
+       localsockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+       if(localsockfd < 0)
+       {
+               SEC_SVR_DBG("%s", "Error on socket()");
+               return SECURITY_SERVER_ERROR_SOCKET;
+       }
+
+       /* Make socket as non blocking */
+       if((flags = fcntl(localsockfd, F_GETFL, 0)) < 0 || 
+                       fcntl(localsockfd, F_SETFL, flags | O_NONBLOCK) < 0)
+       {
+               close(localsockfd);
+               SEC_SVR_DBG("%s", "Cannot go to nonblocking mode");
+               return SECURITY_SERVER_ERROR_SOCKET;
+       }
+
+       bzero(&clientaddr, sizeof(clientaddr));
+       clientaddr.sun_family = AF_UNIX;
+       strncpy(clientaddr.sun_path, SECURITY_SERVER_SOCK_PATH, strlen(SECURITY_SERVER_SOCK_PATH));
+       clientaddr.sun_path[strlen(SECURITY_SERVER_SOCK_PATH)] = 0;
+       client_len = sizeof(clientaddr);
+
+       ret = connect(localsockfd, (struct sockaddr*)&clientaddr, client_len);
+       if( ret < 0)
+       {
+               if(errno == EINPROGRESS)
+               {
+                       SEC_SVR_DBG("%s", "Connection is in progress");
+                       ret = check_socket_poll(localsockfd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+                       if(ret == SECURITY_SERVER_ERROR_POLL)
+                       {
+                               SEC_SVR_DBG("%s", "poll() error");
+                               close(localsockfd);
+                               return SECURITY_SERVER_ERROR_SOCKET;
+                       }
+                       if(ret == SECURITY_SERVER_ERROR_TIMEOUT)
+                       {
+                               SEC_SVR_DBG("%s", "poll() timeout");
+                               close(localsockfd);
+                               return SECURITY_SERVER_ERROR_SOCKET;
+                       }
+                       ret = connect(localsockfd, (struct sockaddr*)&clientaddr, client_len);
+                       if(ret < 0)
+                       {
+                               SEC_SVR_DBG("%s", "connection failed");
+                               close(localsockfd);
+                               return SECURITY_SERVER_ERROR_SOCKET;
+                       }
+               }
+               else
+               {
+                       SEC_SVR_DBG("%s", "Connection failed");
+                       close(localsockfd);
+                       return SECURITY_SERVER_ERROR_SOCKET;
+               }
+       }
+
+       /* Authenticate the peer is actually security server */
+       ret = authenticate_server(localsockfd);
+       if(ret  != SECURITY_SERVER_SUCCESS)
+       {
+               close(localsockfd);
+               SEC_SVR_DBG("Authentication failed. %d", ret);
+               return ret;
+       }
+       *fd = localsockfd;
+       return SECURITY_SERVER_SUCCESS;
+}
+
+/* Accept a new client connection */
+int accept_client(int server_sockfd)
+{
+       /* Call poll() to wait for socket connection */
+       int retval, localsockfd;
+       struct sockaddr_un clientaddr;
+       unsigned int client_len;
+
+       client_len = sizeof(clientaddr);
+
+       /* Check poll */
+       retval = check_socket_poll(server_sockfd, POLLIN, SECURITY_SERVER_ACCEPT_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "Error on polling");
+               return SECURITY_SERVER_ERROR_SOCKET;
+       }
+
+       /* Timed out */
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               /*SEC_SVR_DBG("%s", "accept() timeout");*/
+               return SECURITY_SERVER_ERROR_TIMEOUT;
+       }
+
+       localsockfd = accept(server_sockfd, 
+                       (struct sockaddr *)&clientaddr, 
+                       &client_len);
+
+       if(localsockfd < 0)
+       {
+               SEC_SVR_DBG("Cannot accept client. errno=%d", errno);
+               return SECURITY_SERVER_ERROR_SOCKET;
+       }
+       return localsockfd;
+}
+
+/* Minimal check of request packet */
+int validate_header(basic_header hdr)
+{
+       if(hdr.version != SECURITY_SERVER_MSG_VERSION)
+               return SECURITY_SERVER_ERROR_BAD_REQUEST;
+
+       return SECURITY_SERVER_SUCCESS;
+}
+
+/* Send generic response packet to client
+ * 
+ * Generic Response Packet Format 
+ 0                   1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+|---------------------------------------------------------------|
+| version=0x01  |  Message ID   |Message Length (without header)|
+|---------------------------------------------------------------|
+|  return code  |
+-----------------
+*/
+int send_generic_response (int sockfd, unsigned char msgid, unsigned char return_code)
+{
+       response_header hdr;
+       int size;
+
+       /* Assemble header */
+       hdr.basic_hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.basic_hdr.msg_id = msgid;
+       hdr.basic_hdr.msg_len = 0;
+       hdr.return_code = return_code;
+
+       /* Check poll */
+       size = check_socket_poll(sockfd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(size == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       if(size == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+
+       /* Send to client */
+       size = write(sockfd, &hdr, sizeof(hdr));
+
+       if(size < sizeof(hdr))
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       return SECURITY_SERVER_SUCCESS;
+}
+
+/* Send cookie response to client
+ * 
+ * Get Cookie response packet format
+ *  0                   1                   2                   3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ *  |---------------------------------------------------------------|
+ *  | version=0x01  |MessageID=0x02 |       Message Length =20      |
+ *  |---------------------------------------------------------------|
+ *  |  return code  |                                               |
+ *  -----------------                                               |
+ *  |                 cookie (20 bytes)                             |
+ *  |---------------------------------------------------------------|
+*/
+int send_cookie(int sockfd, unsigned char *cookie)
+{
+       response_header hdr;
+       unsigned char msg[SECURITY_SERVER_COOKIE_LEN + sizeof(hdr)];
+       int ret;
+
+       /* Assemble header */
+       hdr.basic_hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.basic_hdr.msg_id = SECURITY_SERVER_MSG_TYPE_COOKIE_RESPONSE;
+       hdr.basic_hdr.msg_len = SECURITY_SERVER_COOKIE_LEN;
+       hdr.return_code = SECURITY_SERVER_RETURN_CODE_SUCCESS;
+
+       memcpy(msg, &hdr, sizeof(hdr));
+       memcpy(msg + sizeof(hdr), cookie, SECURITY_SERVER_COOKIE_LEN);
+
+       /* Check poll */
+       ret = check_socket_poll(sockfd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(ret == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       if(ret == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+
+       ret = write(sockfd, msg, sizeof(hdr) + SECURITY_SERVER_COOKIE_LEN);
+       if(ret <  sizeof(hdr) + SECURITY_SERVER_COOKIE_LEN)
+       {
+               /* Error on writing */
+               SEC_SVR_DBG("Error on write: %d", ret);
+               ret = SECURITY_SERVER_ERROR_SEND_FAILED;
+               return ret;
+       }
+       return SECURITY_SERVER_SUCCESS;
+}
+
+/* Send Object name response *
+ * Get Object name response packet format
+ *  0                   1                   2                   3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x06 |       Message Length          |
+ * |---------------------------------------------------------------|
+ * |  return code  |                                               |
+ * -----------------                                               |
+ * |                 object name                                   |
+ * |---------------------------------------------------------------|
+*/
+int send_object_name(int sockfd, char *obj)
+{
+       response_header hdr;
+       unsigned char msg[strlen(obj) + sizeof(hdr)];
+       int ret;
+
+       hdr.basic_hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.basic_hdr.msg_id = 0x06;
+       hdr.basic_hdr.msg_len = strlen(obj);
+       hdr.return_code = SECURITY_SERVER_RETURN_CODE_SUCCESS;
+
+       memcpy(msg, &hdr, sizeof(hdr));
+       memcpy(msg + sizeof(hdr), obj, strlen(obj));
+
+       /* Check poll */
+       ret = check_socket_poll(sockfd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(ret == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       if(ret == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+
+       ret = write(sockfd, msg, sizeof(hdr) + strlen(obj));
+       if(ret <  sizeof(hdr) + strlen(obj))
+       {
+               /* Error on writing */
+               SEC_SVR_DBG("Error on write: %d", ret);
+               ret = SECURITY_SERVER_ERROR_SEND_FAILED;
+               return ret;
+       }
+       return SECURITY_SERVER_SUCCESS;
+}
+
+/* Send GID response to client
+ * 
+ * Get GID response packet format
+ *  0                   1                   2                   3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x08 |       Message Length = 4      |
+ * |---------------------------------------------------------------|
+ * |  return code  |           gid (first 3 words)                 |
+ * |---------------------------------------------------------------|
+ * |gid(last word) |
+ * |---------------|
+*/
+int send_gid(int sockfd, int gid)
+{
+       response_header hdr;
+       unsigned char msg[sizeof(gid) + sizeof(hdr)];
+       int ret;
+
+       /* Assemble header */
+       hdr.basic_hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.basic_hdr.msg_id = SECURITY_SERVER_MSG_TYPE_GID_RESPONSE;
+       hdr.basic_hdr.msg_len = sizeof(gid);
+       hdr.return_code = SECURITY_SERVER_RETURN_CODE_SUCCESS;
+
+       /* Perpare packet */
+       memcpy(msg, &hdr, sizeof(hdr));
+       memcpy(msg + sizeof(hdr), &gid, sizeof(gid));
+
+       /* Check poll */
+       ret = check_socket_poll(sockfd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(ret == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       if(ret == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+
+       /* Send it */
+       ret = write(sockfd, msg, sizeof(hdr) + sizeof(gid));
+       if(ret <  sizeof(hdr) + sizeof(gid))
+       {
+               /* Error on writing */
+               SEC_SVR_DBG("Error on write(): %d", ret);
+               ret = SECURITY_SERVER_ERROR_SEND_FAILED;
+               return ret;
+       }
+       return SECURITY_SERVER_SUCCESS;
+}
+
+/* Send PID response to client
+ * 
+ * Get PID response packet format
+ *  0                   1                   2                   3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x0a |       Message Length = 4      |
+ * |---------------------------------------------------------------|
+ * |  return code  |           pid (first 3 words)                 |
+ * |---------------------------------------------------------------|
+ * |pid(last word) |
+ * |---------------|
+*/
+int send_pid(int sockfd, int pid)
+{
+       response_header hdr;
+       unsigned char msg[sizeof(pid) + sizeof(hdr)];
+       int ret;
+
+       /* Assemble header */
+       hdr.basic_hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.basic_hdr.msg_id = SECURITY_SERVER_MSG_TYPE_PID_RESPONSE;
+       hdr.basic_hdr.msg_len = sizeof(pid);
+       hdr.return_code = SECURITY_SERVER_RETURN_CODE_SUCCESS;
+
+       /* Perpare packet */
+       memcpy(msg, &hdr, sizeof(hdr));
+       memcpy(msg + sizeof(hdr), &pid, sizeof(pid));
+
+       /* Check poll */
+       ret = check_socket_poll(sockfd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(ret == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       if(ret == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+
+       /* Send it */
+       ret = write(sockfd, msg, sizeof(hdr) + sizeof(pid));
+       if(ret <  sizeof(hdr) + sizeof(pid))
+       {
+               /* Error on writing */
+               SEC_SVR_DBG("Error on write(): %d", ret);
+               ret = SECURITY_SERVER_ERROR_SEND_FAILED;
+               return ret;
+       }
+       return SECURITY_SERVER_SUCCESS;
+}
+
+/* Send Check password response to client
+ * 
+ * Check password response packet format
+ *  0                   1                   2                   3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ * |---------------------------------------------------------------|
+ * | version=0x01  |   MessageID   |       Message Length = 12     |
+ * |---------------------------------------------------------------|
+ * |  return code  |           attempts (first 3 words)            |
+ * |---------------------------------------------------------------|
+ * |attempts(rest) |          max_attempts (first 3 words)         |
+ * |---------------|-----------------------------------------------|
+ * | max_attempts  |          expire_in_days (first 3 words)       |
+ * |---------------------------------------------------------------|
+ * |expire_in_days |
+ * |----------------
+ */
+int send_pwd_response(const int sockfd, 
+       const unsigned char msg_id,
+       const unsigned char return_code, 
+       const unsigned int current_attempts, 
+       const unsigned int max_attempts, 
+       const unsigned int expire_time)
+{
+       response_header hdr;
+       unsigned int expire_secs;
+       unsigned char msg[sizeof(hdr) + sizeof(current_attempts) + sizeof(max_attempts) + sizeof(expire_secs)];
+       int ret, ptr = 0;
+       
+
+       /* Assemble header */
+       hdr.basic_hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.basic_hdr.msg_id = msg_id;
+       hdr.basic_hdr.msg_len = sizeof(unsigned int) * 3;
+       hdr.return_code = return_code;
+
+       /* Perpare packet */
+       memcpy(msg, &hdr, sizeof(hdr));
+       ptr += sizeof(hdr);
+       memcpy(msg + ptr, &current_attempts, sizeof(current_attempts));
+       ptr += sizeof(current_attempts);
+       memcpy(msg + ptr, &max_attempts, sizeof(max_attempts));
+       ptr += sizeof(max_attempts);
+       memcpy(msg + ptr, &expire_time, sizeof(expire_time));
+       ptr += sizeof(expire_time);
+
+       /* Check poll */
+       ret = check_socket_poll(sockfd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(ret == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "Server: poll() error");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       if(ret == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "Server: poll() timeout");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+
+       /* Send it */
+       ret = write(sockfd, msg, ptr);
+       if(ret <  ptr)
+       {
+               /* Error on writing */
+               SEC_SVR_DBG("Server: ERROR on write(): %d", ret);
+               ret = SECURITY_SERVER_ERROR_SEND_FAILED;
+               return ret;
+       }
+       return SECURITY_SERVER_SUCCESS;
+}
+
+/* Send cookie request packet to security server *
+ * 
+ * Message format
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x01 |       Message Length = 0      |
+ * |---------------------------------------------------------------|
+ */
+int send_cookie_request(int sock_fd)
+{
+       basic_header hdr;
+       int retval;
+
+       /* Assemble header */
+       hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.msg_id = SECURITY_SERVER_MSG_TYPE_COOKIE_REQUEST;
+       hdr.msg_len = 0;
+
+       /* Check poll */
+       retval = check_socket_poll(sock_fd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+
+       /* Send to server */
+       retval = write(sock_fd, &hdr, sizeof(hdr));
+       if(retval < sizeof(hdr))
+       {
+               /* Write error */
+               SEC_SVR_DBG("Error on write(): %d", retval);
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       return SECURITY_SERVER_SUCCESS; 
+}
+
+/* Send GID request message to security server
+ *
+ * Message format
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x07 |   Message Length = variable   |
+ * |---------------------------------------------------------------|
+ * |                                                               |
+ * |                   Object name (variable)                      |
+ * |                                                               |
+ * |---------------------------------------------------------------|
+ */
+int send_gid_request(int sock_fd, const char* object)
+{
+       basic_header hdr;
+       int retval = 0, send_len = 0;
+       unsigned char *buf = NULL;
+
+       if(strlen(object) > SECURITY_SERVER_MAX_OBJ_NAME)
+       {
+               /* Object name is too big*/
+               SEC_SVR_DBG("Object name is too big %dbytes", strlen(object));
+               return SECURITY_SERVER_ERROR_INPUT_PARAM;
+       }
+
+       hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.msg_id = SECURITY_SERVER_MSG_TYPE_GID_REQUEST;
+       hdr.msg_len = strlen(object);
+
+       send_len = sizeof(hdr) + strlen(object);
+
+       buf = malloc(send_len);
+       if(buf == NULL)
+       {
+               SEC_SVR_DBG("%s", "out of memory");
+               return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+       }
+
+       memcpy(buf, &hdr, sizeof(hdr));
+       memcpy(buf + sizeof(hdr), object, strlen(object));
+
+       /* Check poll */
+       retval = check_socket_poll(sock_fd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               retval = SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+       }
+
+       retval = write(sock_fd, buf, send_len);
+       if(retval < send_len)
+       {
+               /* Write error */
+               SEC_SVR_DBG("Error on write(): %d. errno=%d, sockfd=%d", retval, errno, sock_fd);
+               retval = SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       else
+               retval = SECURITY_SERVER_SUCCESS;
+
+error:
+       if(buf != NULL)
+               free(buf);
+
+       return retval;  
+}
+
+/* Send object name request message to security server *
+ *
+ * Message format
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x05 |       Message Length = 4      |
+ * |---------------------------------------------------------------|
+ * |                               gid                             |
+ * |---------------------------------------------------------------|
+ */
+int send_object_name_request(int sock_fd, int gid)
+{
+       basic_header hdr;
+       int retval;
+       unsigned char buf[sizeof(hdr) + sizeof(gid)];
+
+       /* Assemble header */
+       hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.msg_id = SECURITY_SERVER_MSG_TYPE_OBJECT_NAME_REQUEST;
+       hdr.msg_len = sizeof(gid);
+
+       memcpy(buf, &hdr, sizeof(hdr));
+       memcpy(buf + sizeof(hdr), &gid, sizeof(gid));
+
+       /* Check poll */
+       retval = check_socket_poll(sock_fd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+
+       /* Send to server */
+       retval = write(sock_fd, buf, sizeof(buf));
+       if(retval < sizeof(buf))
+       {
+               /* Write error */
+               SEC_SVR_DBG("Error on write(): %d", retval);
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       return SECURITY_SERVER_SUCCESS; 
+}
+
+/* Send privilege check request message to security server *
+ *
+ * Message format
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x03 |      Message Length = 24      |
+ * |---------------------------------------------------------------|
+ * |                                                               |
+ * |                                                               |
+ * |                      Cookie (20bytes)                         |
+ * |                                                               |
+ * |                                                               |
+ * |---------------------------------------------------------------|
+ * |                            GID                                |
+ * |---------------------------------------------------------------|
+ */
+int send_privilege_check_request(int sock_fd, const char*cookie, int gid)
+{
+       basic_header hdr;
+       int retval;
+       unsigned char buf[sizeof(hdr) + sizeof(gid) + SECURITY_SERVER_COOKIE_LEN];
+
+       /* Assemble header */
+       hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.msg_id = SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_REQUEST;
+       hdr.msg_len = sizeof(gid) + SECURITY_SERVER_COOKIE_LEN;
+
+       memcpy(buf, &hdr, sizeof(hdr));
+       memcpy(buf + sizeof(hdr), cookie, SECURITY_SERVER_COOKIE_LEN);
+       memcpy(buf + sizeof(hdr) + SECURITY_SERVER_COOKIE_LEN, &gid, sizeof(gid));
+
+       /* Check poll */
+       retval = check_socket_poll(sock_fd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+
+       /* Send to server */
+       retval = write(sock_fd, buf, sizeof(buf));
+       if(retval < sizeof(buf))
+       {
+               /* Write error */
+               SEC_SVR_DBG("Error on write(): %d", retval);
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       return SECURITY_SERVER_SUCCESS;
+}
+
+/* Send PID check request message to security server *
+ *
+ * Message format
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x09 |      Message Length = 20      |
+ * |---------------------------------------------------------------|
+ * |                                                               |
+ * |                                                               |
+ * |                      Cookie (20bytes)                         |
+ * |                                                               |
+ * |                                                               |
+ * |---------------------------------------------------------------|
+ */
+int send_pid_request(int sock_fd, const char*cookie)
+{
+       basic_header hdr;
+       int retval;
+       unsigned char buf[sizeof(hdr) + SECURITY_SERVER_COOKIE_LEN];
+
+       /* Assemble header */
+       hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.msg_id = SECURITY_SERVER_MSG_TYPE_PID_REQUEST;
+       hdr.msg_len = SECURITY_SERVER_COOKIE_LEN;
+
+       memcpy(buf, &hdr, sizeof(hdr));
+       memcpy(buf + sizeof(hdr), cookie, SECURITY_SERVER_COOKIE_LEN);
+
+       /* Check poll */
+       retval = check_socket_poll(sock_fd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+
+       /* Send to server */
+       retval = write(sock_fd, buf, sizeof(buf));
+       if(retval < sizeof(buf))
+       {
+               /* Write error */
+               SEC_SVR_DBG("Error on write(): %d", retval);
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       return SECURITY_SERVER_SUCCESS;
+}
+
+
+/* Send debug tool launch request message to security server *
+ *
+ * Message format
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x0b |       Message Length          |
+ * |---------------------------------------------------------------|
+ * |                        total # of args                        |
+ * |---------------------------------------------------------------|
+ * |                        1st argv length                        |
+ * |---------------------------------------------------------------|
+ * |                                                               |
+ * |                            1st argv                           |
+ * |                                                               |
+ * |---------------------------------------------------------------|
+ * |                        2nd argv length                        |
+ * |---------------------------------------------------------------|
+ * |                                                               |
+ * |                            2nd argv                           |
+ * |                                                               |
+ * |---------------------------------------------------------------|
+ * |                                ...                            |
+ * |---------------------------------------------------------------|
+ * |                        nth argv length                        |
+ * |---------------------------------------------------------------|
+ * |                                                               |
+ * |                            nth argv                           |
+ * |                                                               |
+ * |---------------------------------------------------------------|
+ */
+int send_launch_tool_request(int sock_fd, int argc, const char **argv)
+{
+       basic_header hdr;
+       int retval, total_length = 0, ptr, i, tempnum;
+       unsigned char *buf = NULL;
+
+       for (i=0;i<argc;i++)
+       {
+               if(argv[i] == NULL)
+               {
+                       SEC_SVR_DBG("Error: %dth argv is NULL", i);
+                       return SECURITY_SERVER_ERROR_INPUT_PARAM;
+               }
+               total_length += strlen(argv[i]);
+       }
+
+       if(total_length < 1)
+       {
+               SEC_SVR_DBG("Error: There is a problem in argv. [%d]", total_length);
+               return SECURITY_SERVER_ERROR_INPUT_PARAM;
+       }
+       total_length += sizeof(hdr) + sizeof(int) +(argc * sizeof(int));
+
+       if(total_length > 0xffff)
+       {
+               SEC_SVR_DBG("Buffer overflow. too big payload. [%d]", total_length);
+               return SECURITY_SERVER_ERROR_INPUT_PARAM;
+       }
+
+       buf = malloc(total_length);
+       if(buf == NULL)
+       {
+               SEC_SVR_DBG("%s", "Error: failed to malloc()");
+               return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+       }
+
+       /* Assemble header */
+       hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.msg_id = SECURITY_SERVER_MSG_TYPE_TOOL_REQUEST;
+       hdr.msg_len = (unsigned short)total_length;
+       memcpy(buf, &hdr, sizeof(hdr));
+       ptr = sizeof(hdr);
+       memcpy(buf + ptr, &argc, sizeof(int));
+       ptr += sizeof(hdr);
+
+       /* Assemple each argv length and value */
+       for(i=0;i<argc;i++)
+       {
+               tempnum = strlen(argv[i]);
+               memcpy(buf + ptr, &tempnum, sizeof(int));
+               ptr += sizeof(int);
+               memcpy(buf + ptr, argv[i], tempnum);
+               ptr += tempnum;
+       }
+
+       /* Check poll */
+       retval = check_socket_poll(sock_fd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+               
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+       }
+
+       /* Send to server */
+       retval = write(sock_fd, buf, total_length);
+       if(retval < sizeof(buf))
+       {
+               /* Write error */
+               SEC_SVR_DBG("Error on write(): %d", retval);
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+       }
+       retval = SECURITY_SERVER_SUCCESS;
+
+error:
+       if(buf != NULL)
+               free(buf);
+       return retval;
+}
+
+/* Send validate password request message to security server *
+ *
+ * Message format
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x0d |       Message Length          |
+ * |---------------------------------------------------------------|
+ */
+int send_valid_pwd_request(int sock_fd)
+{
+       basic_header hdr;
+       int retval;
+
+       hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.msg_id = SECURITY_SERVER_MSG_TYPE_VALID_PWD_REQUEST;
+       hdr.msg_len = 0;
+
+       /* Check poll */
+       retval = check_socket_poll(sock_fd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+               
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+       }
+
+       /* Send to server */
+       retval = write(sock_fd, &hdr, sizeof(hdr));
+       if(retval < sizeof(hdr))
+       {
+               /* Write error */
+               SEC_SVR_DBG("Error on write(): %d", retval);
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+       }
+       retval = SECURITY_SERVER_SUCCESS;
+
+error:
+       return retval;
+}
+
+/* Send password set request message to security server *
+ *
+ * Message format
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x0f |       Message Length          |
+ * |---------------------------------------------------------------|
+ * |  cur_pwd_len  |  new_pwd_len  |                               |
+ * |--------------------------------                               |
+ * |                            cur pwd                            |
+ * |---------------------------------------------------------------|
+ * |                                                               |
+ * |                            new pwd                            |
+ * |                                                               |
+ * |---------------------------------------------------------------|
+ * |                         max attempts                          |
+ * |---------------------------------------------------------------|
+ * |                         valid days                            |
+ * |---------------------------------------------------------------|
+ */
+int send_set_pwd_request(int sock_fd, 
+                       const char*cur_pwd, 
+                       const char*new_pwd,
+                       const unsigned int max_challenge,
+                       const unsigned int valid_period_in_days)
+{
+       basic_header hdr;
+       int retval, total_length = 0, ptr;
+       unsigned char *buf = NULL, cur_pwd_len, new_pwd_len;
+
+       if(cur_pwd == NULL)
+               cur_pwd_len = 0;
+       else
+               cur_pwd_len = strlen(cur_pwd);
+       new_pwd_len = strlen(new_pwd);
+
+       total_length += sizeof(hdr) + sizeof(char) + sizeof(char) + cur_pwd_len
+               + new_pwd_len + sizeof(unsigned int) + sizeof(unsigned int);
+
+       buf = malloc(total_length);
+       if(buf == NULL)
+       {
+               SEC_SVR_DBG("%s", "Error: failed to malloc()");
+               return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+       }
+
+       /* Assemble header */
+       hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.msg_id = SECURITY_SERVER_MSG_TYPE_SET_PWD_REQUEST;
+       hdr.msg_len = (unsigned short)total_length;
+       memcpy(buf, &hdr, sizeof(hdr));
+       ptr = sizeof(hdr);
+       memcpy(buf + ptr, &cur_pwd_len, sizeof(char));
+       ptr += sizeof(char);
+       memcpy(buf + ptr, &new_pwd_len, sizeof(char));
+       ptr += sizeof(char);
+       if(cur_pwd != NULL)
+       {
+               memcpy(buf + ptr, cur_pwd, cur_pwd_len);
+               ptr += cur_pwd_len;
+       }
+       memcpy(buf + ptr, new_pwd, new_pwd_len);
+       ptr += new_pwd_len;
+       memcpy(buf + ptr, &max_challenge, sizeof(unsigned int));
+       ptr += sizeof(unsigned int);
+       memcpy(buf + ptr, &valid_period_in_days, sizeof(unsigned int));
+
+       /* Check poll */
+       retval = check_socket_poll(sock_fd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+               
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+       }
+
+       /* Send to server */
+       retval = write(sock_fd, buf, total_length);
+       if(retval < sizeof(buf))
+       {
+               /* Write error */
+               SEC_SVR_DBG("Error on write(): %d", retval);
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+       }
+       retval = SECURITY_SERVER_SUCCESS;
+
+error:
+       if(buf != NULL)
+               free(buf);
+       return retval;
+}
+
+/* Send password reset request message to security server *
+ *
+ * Message format
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x11 |       Message Length          |
+ * |---------------------------------------------------------------|
+ * |  new_pwd_len  |                                               |
+ * |---------------------------------------------------------------|
+ * |                                                               |
+ * |                            new pwd                            |
+ * |                                                               |
+ * |---------------------------------------------------------------|
+ * |                         max attempts                          |
+ * |---------------------------------------------------------------|
+ * |                         valid days                            |
+ * |---------------------------------------------------------------|
+ */
+int send_reset_pwd_request(int sock_fd, 
+                       const char*new_pwd,
+                       const unsigned int max_challenge,
+                       const unsigned int valid_period_in_days)
+{
+       basic_header hdr;
+       int retval, total_length = 0, ptr;
+       unsigned char *buf = NULL, new_pwd_len;
+
+       new_pwd_len = strlen(new_pwd);
+
+       total_length += sizeof(hdr) + sizeof(char) + new_pwd_len + sizeof(unsigned int) + 
+               sizeof(unsigned int);
+
+       buf = malloc(total_length);
+       if(buf == NULL)
+       {
+               SEC_SVR_DBG("%s", "Error: failed to malloc()");
+               return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+       }
+
+       /* Assemble header */
+       hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.msg_id = SECURITY_SERVER_MSG_TYPE_RESET_PWD_REQUEST;
+       hdr.msg_len = (unsigned short)total_length;
+       memcpy(buf, &hdr, sizeof(hdr));
+       ptr = sizeof(hdr);
+       memcpy(buf + ptr, &new_pwd_len, sizeof(char));
+       ptr += sizeof(char);
+       memcpy(buf + ptr, new_pwd, new_pwd_len);
+       ptr += new_pwd_len;
+       memcpy(buf + ptr, &max_challenge, sizeof(unsigned int));
+       ptr += sizeof(unsigned int);
+       memcpy(buf + ptr, &valid_period_in_days, sizeof(unsigned int));
+
+       /* Check poll */
+       retval = check_socket_poll(sock_fd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+               
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+       }
+
+       /* Send to server */
+       retval = write(sock_fd, buf, total_length);
+       if(retval < sizeof(buf))
+       {
+               /* Write error */
+               SEC_SVR_DBG("Error on write(): %d", retval);
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+       }
+       retval = SECURITY_SERVER_SUCCESS;
+
+error:
+       if(buf != NULL)
+               free(buf);
+       return retval;
+}
+
+/* Send password check request message to security server *
+ *
+ * Message format
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x13 |       Message Length          |
+ * |---------------------------------------------------------------|
+ * | challenge_len |                                               |
+ * |---------------                                                |
+ * |                          challenge                            |
+ * |---------------------------------------------------------------|
+ */
+int send_chk_pwd_request(int sock_fd, const char*challenge)
+{
+       basic_header hdr;
+       int retval, total_length = 0, ptr;
+       unsigned char *buf = NULL, challenge_len;
+
+       challenge_len = strlen(challenge);
+
+       total_length += sizeof(hdr) + sizeof(char) + challenge_len;
+
+       buf = malloc(total_length);
+       if(buf == NULL)
+       {
+               SEC_SVR_DBG("%s", "Error: failed to malloc()");
+               return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+       }
+
+       /* Assemble header */
+       hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.msg_id = SECURITY_SERVER_MSG_TYPE_CHK_PWD_REQUEST;
+       hdr.msg_len = (unsigned short)total_length;
+       memcpy(buf, &hdr, sizeof(hdr));
+       ptr = sizeof(hdr);
+       memcpy(buf + ptr, &challenge_len, sizeof(char));
+       ptr += sizeof(char);
+       memcpy(buf + ptr, challenge, challenge_len);
+       ptr += sizeof(char);
+
+       /* Check poll */
+       retval = check_socket_poll(sock_fd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+               
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+       }
+
+       /* Send to server */
+       retval = write(sock_fd, buf, total_length);
+       if(retval < sizeof(buf))
+       {
+               /* Write error */
+               SEC_SVR_DBG("Error on write(): %d", retval);
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+       }
+       retval = SECURITY_SERVER_SUCCESS;
+
+error:
+       if(buf != NULL)
+               free(buf);
+       return retval;
+}
+
+/* Send password history set request message to security server *
+ *
+ * Message format
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x15 |       Message Length          |
+ * |---------------------------------------------------------------|
+ * | challenge_len |
+ * |----------------
+ */
+int send_set_pwd_history_request(int sock_fd, int num)
+{
+       basic_header hdr;
+       int retval, total_length = 0, ptr;
+       unsigned char history;
+       unsigned char buf[sizeof(hdr) + sizeof(history)];
+
+       total_length = sizeof(hdr) + sizeof(char);
+       history = (unsigned char) num;
+
+       /* Assemble header */
+       hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.msg_id = SECURITY_SERVER_MSG_TYPE_SET_PWD_HISTORY_REQUEST;
+       hdr.msg_len = (unsigned short)total_length;
+       memcpy(buf, &hdr, sizeof(hdr));
+       ptr = sizeof(hdr);
+       memcpy(buf + ptr, &history, sizeof(char));
+       ptr += sizeof(char);
+
+       /* Check poll */
+       retval = check_socket_poll(sock_fd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+               
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+       }
+
+       /* Send to server */
+       retval = write(sock_fd, buf, ptr);
+       if(retval < sizeof(buf))
+       {
+               /* Write error */
+               SEC_SVR_DBG("Error on write(): %d", retval);
+               retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+               goto error;
+       }
+       retval = SECURITY_SERVER_SUCCESS;
+
+error:
+       return retval;
+}
+
+/* Receive request header */
+int recv_hdr(int client_sockfd, basic_header *basic_hdr)
+{
+       int retval;
+
+       /* Check poll */
+       retval = check_socket_poll(client_sockfd, POLLIN, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               return SECURITY_SERVER_ERROR_SOCKET;
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               return SECURITY_SERVER_ERROR_TIMEOUT;
+       }
+
+       /* Receive request header first */
+       retval = read(client_sockfd, basic_hdr, sizeof(basic_header));
+       if(retval < sizeof(basic_header))
+       {
+               SEC_SVR_DBG("read failed. closing socket %d", retval);
+               return SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+
+       /* Validate header */
+       retval = validate_header(*basic_hdr);
+       return retval;
+}
+
+
+/* Receive check privilege request packet body */
+int recv_check_privilege_request(int sockfd, unsigned char *requested_cookie, int *requested_privilege)
+{
+       int retval;
+       retval = read(sockfd, requested_cookie, SECURITY_SERVER_COOKIE_LEN);
+       if(retval < SECURITY_SERVER_COOKIE_LEN)
+       {
+               SEC_SVR_DBG("Received cookie size is too small: %d", retval);
+               return SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+
+       retval = read(sockfd, requested_privilege, sizeof(int));
+       if(retval < sizeof(int))
+       {
+               SEC_SVR_DBG("privilege size is too small: %d", retval);
+               return SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+       return SECURITY_SERVER_SUCCESS;
+}
+
+/* Receive pid request packet body */
+int recv_pid_request(int sockfd, unsigned char *requested_cookie)
+{
+       int retval;
+       retval = read(sockfd, requested_cookie, SECURITY_SERVER_COOKIE_LEN);
+       if(retval < SECURITY_SERVER_COOKIE_LEN)
+       {
+               SEC_SVR_DBG("Received cookie size is too small: %d", retval);
+               return SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+       return SECURITY_SERVER_SUCCESS;
+}
+
+/* Receive pid request packet body */
+int recv_launch_tool_request(int sockfd, int argc, char *argv[])
+{
+       int retval, i, argv_len;
+
+       argv[0] = malloc(strlen(SECURITY_SERVER_DEBUG_TOOL_PATH) + 1);
+       strncpy(argv[0], SECURITY_SERVER_DEBUG_TOOL_PATH, (strlen(SECURITY_SERVER_DEBUG_TOOL_PATH) + 1));
+
+       for(i=1;i<argc;i++)
+       {
+               retval = read(sockfd, &argv_len, sizeof(int));
+               if(retval < sizeof(int))
+               {
+                       SEC_SVR_DBG("Error: argv length recieve failed: %d", retval);
+                       free_argv(argv, argc);
+                       return SECURITY_SERVER_ERROR_RECV_FAILED;
+               }
+
+               argv[i] = malloc(argv_len + 1);
+               if(argv[i] == NULL)
+               {
+                       SEC_SVR_DBG("Error: malloc() failed: %d", retval);
+                       free_argv(argv, argc);
+                       return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+               }
+
+               memset(argv[i], 0x00, argv_len + 1);
+               retval = read(sockfd, argv[i], argv_len);
+               if(retval < argv_len)
+               {
+                       SEC_SVR_DBG("Error: argv recieve failed: %d", retval);
+                       free_argv(argv, argc);
+                       return SECURITY_SERVER_ERROR_RECV_FAILED;
+               }
+       }
+
+       return SECURITY_SERVER_SUCCESS;
+}
+
+int recv_generic_response(int sockfd, response_header *hdr)
+{
+       int retval;
+
+       /* Check poll */
+       retval = check_socket_poll(sockfd, POLLIN, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "Client: poll() error");
+               return SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "Client: poll() timeout");
+               return SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+
+       /* Receive response */
+       retval = read(sockfd, hdr, sizeof(response_header));
+       if(retval < sizeof(hdr) )
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Client: Receive failed %d", retval);
+               return  SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+
+       if(hdr->return_code != SECURITY_SERVER_RETURN_CODE_SUCCESS)
+       {
+               SEC_SVR_DBG("Client: return code is not success: %d", hdr->return_code);
+               return return_code_to_error_code(hdr->return_code);
+       }
+       return SECURITY_SERVER_SUCCESS;
+}
+
+int recv_get_gid_response(int sockfd, response_header *hdr, int *gid)
+{
+       int retval;
+
+       retval = recv_generic_response(sockfd, hdr);
+       if(retval != SECURITY_SERVER_SUCCESS)
+               return return_code_to_error_code(hdr->return_code);
+
+       retval = read(sockfd, gid, sizeof(int));
+       if(retval < sizeof(int))
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Receive failed %d", retval);
+               return  SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+       return SECURITY_SERVER_SUCCESS;
+}
+
+int recv_get_object_name(int sockfd, response_header *hdr, char *object, int max_object_size)
+{
+       int retval;
+       char *local_obj_name = NULL;
+
+       /* Check poll */
+       retval = check_socket_poll(sockfd, POLLIN, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               return SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               return SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+
+       /* Read response */
+       retval = read(sockfd, hdr, sizeof(response_header));
+       if(retval < sizeof(hdr) )
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("cannot recv respons: %d", retval);
+               return SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+
+       if(hdr->return_code == SECURITY_SERVER_RETURN_CODE_SUCCESS)
+       {
+               if(max_object_size < hdr->basic_hdr.msg_len)
+               {
+                       SEC_SVR_DBG("Object name is too small need %d bytes, but %d bytes", hdr->basic_hdr.msg_len, max_object_size);
+                       return SECURITY_SERVER_ERROR_BUFFER_TOO_SMALL;
+               }
+               if(hdr->basic_hdr.msg_len > SECURITY_SERVER_MAX_OBJ_NAME)
+               {
+                       SEC_SVR_DBG("Received object name is too big. %d", hdr->basic_hdr.msg_len);
+                       return SECURITY_SERVER_ERROR_BAD_RESPONSE;
+               }
+
+               local_obj_name = malloc(hdr->basic_hdr.msg_len + 1);
+               if(local_obj_name == NULL)
+               {
+                       SEC_SVR_DBG("%s", "Out of memory error");
+                       return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+               }
+               
+               retval = read(sockfd, local_obj_name, hdr->basic_hdr.msg_len);
+               if(retval < (hdr->basic_hdr.msg_len))
+               {
+                       /* Error on socket */
+                       SEC_SVR_DBG("read() failed: %d", retval);
+                       if(local_obj_name != NULL)
+                               free(local_obj_name);
+                       return SECURITY_SERVER_ERROR_RECV_FAILED;
+               }
+               memcpy(object, local_obj_name, hdr->basic_hdr.msg_len);
+               object[hdr->basic_hdr.msg_len] = 0;
+               retval = SECURITY_SERVER_SUCCESS;
+       }
+       else
+       {
+               SEC_SVR_DBG("Error received. return code: %d", hdr->return_code);
+               retval = return_code_to_error_code(hdr->return_code);
+               return retval;
+       }
+
+       if(local_obj_name != NULL)
+               free(local_obj_name);
+       return SECURITY_SERVER_SUCCESS;
+}
+
+int recv_cookie(int sockfd, response_header *hdr, char *cookie)
+{
+       int retval;
+
+       retval = recv_generic_response(sockfd, hdr);
+       if(retval != SECURITY_SERVER_SUCCESS)
+               return return_code_to_error_code(hdr->return_code);
+
+       retval = read(sockfd, cookie, SECURITY_SERVER_COOKIE_LEN);
+       if(retval < SECURITY_SERVER_COOKIE_LEN)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("read() failed: %d", retval);
+               return SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+       return SECURITY_SERVER_SUCCESS;
+}
+
+int recv_privilege_check_response(int sockfd, response_header *hdr)
+{
+       int retval;
+
+       retval = recv_generic_response(sockfd, hdr);
+       if(hdr->return_code != SECURITY_SERVER_RETURN_CODE_ACCESS_GRANTED &&
+                       hdr->return_code != SECURITY_SERVER_RETURN_CODE_ACCESS_DENIED) 
+       {
+               SEC_SVR_DBG("response error: %d", hdr->return_code);
+               return return_code_to_error_code(hdr->return_code);
+       }
+       return SECURITY_SERVER_SUCCESS;
+}
+
+int recv_pid_response(int sockfd, response_header *hdr, int *pid)
+{
+       int retval;
+
+       retval = recv_generic_response(sockfd, hdr);
+       if(retval != SECURITY_SERVER_SUCCESS)
+               return return_code_to_error_code(hdr->return_code);
+
+       retval = read(sockfd, pid, sizeof(int));
+       if(retval < sizeof(int))
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Client: Receive failed %d", retval);
+               return  SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+       return SECURITY_SERVER_SUCCESS;
+}
+
+int recv_pwd_response(int sockfd, response_header *hdr, 
+       unsigned int *current_attempts, 
+       unsigned int *max_attempts, 
+       unsigned int *valid_secs)
+{
+       int retval;
+       *current_attempts = 0;
+       *max_attempts = 0;
+       *valid_secs = 0;
+
+       retval = recv_generic_response(sockfd, hdr);
+
+       switch(retval)
+       {
+               case SECURITY_SERVER_ERROR_PASSWORD_EXIST:
+               case SECURITY_SERVER_ERROR_NO_PASSWORD:
+               case SECURITY_SERVER_ERROR_PASSWORD_MISMATCH:
+               case SECURITY_SERVER_ERROR_PASSWORD_RETRY_TIMER:
+               case SECURITY_SERVER_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED:
+               case SECURITY_SERVER_ERROR_PASSWORD_EXPIRED:
+               case SECURITY_SERVER_ERROR_PASSWORD_REUSED:
+               case SECURITY_SERVER_SUCCESS:
+                       break;
+               default:
+                       return return_code_to_error_code(hdr->return_code);
+       }
+
+       retval = read(sockfd, current_attempts, sizeof(unsigned int));
+       if(retval < sizeof(unsigned int))
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Client: Receive failed %d", retval);
+               return  SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+       retval = read(sockfd, max_attempts, sizeof(unsigned int));
+       if(retval < sizeof(unsigned int))
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Client: Receive failed %d", retval);
+               return  SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+       retval = read(sockfd, valid_secs, sizeof(unsigned int));
+       if(retval < sizeof(unsigned int))
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Client: Receive failed %d", retval);
+               return  SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+}
+
+/* Authenticate client application *
+ * Currently it only gets peer's credential information only *
+ * If we need, we can extend in the futer */
+int authenticate_client_application(int sockfd, int *pid, int *uid)
+{
+       int retval = 0;
+       struct ucred cr;
+       unsigned int cl = sizeof(cr);
+
+       /* get PID of socket peer */
+       if(getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cr, &cl) != 0)
+       {
+               retval = SECURITY_SERVER_ERROR_SOCKET;
+               SEC_SVR_DBG("%s", "getsockopt failed");
+               *pid = 0;
+               goto error;
+       }
+       *pid = cr.pid;
+       *uid = cr.uid;
+
+       /* Authenticate client that it's real client application */
+       /* TBA */
+       
+error:
+       return retval;
+}
+
+/* Checking client is pre-defined middleware daemons *
+ * Check privilege API is only allowed to middleware daemons *
+ * cmd line list of middleware daemons are listed in
+ * /usr/share/security-server/mw-list */
+int search_middleware_cmdline(char *cmdline)
+{
+       FILE *fp = NULL;
+       int ret;
+       char middleware[SECURITY_SERVER_MAX_PATH_LEN];
+
+       /* Open the list file */
+       fp = fopen(SECURITY_SERVER_MIDDLEWARE_LIST_PATH, "r");
+       if(fp == NULL)
+       {
+               /* error on file */
+               SEC_SVR_DBG("%s", "Error oening mw-list file");
+               return SECURITY_SERVER_ERROR_FILE_OPERATION; 
+       }
+
+       /* Search each line */
+       ret = SECURITY_SERVER_ERROR_AUTHENTICATION_FAILED;
+       while(fgets(middleware, SECURITY_SERVER_MAX_PATH_LEN, fp) != NULL)
+       {
+               if(strncmp(middleware, cmdline, strlen(middleware)-1) == 0)
+               {
+                       /* found */
+                       SEC_SVR_DBG("%s", "found matching cmd line");
+                       ret = SECURITY_SERVER_SUCCESS;
+                       break;
+               }
+
+       }
+       if(fp != NULL)
+               fclose(fp);
+       return ret;
+}
+
+/* Authenticate the application is middleware daemon
+ * The middleware must run as root and the cmd line must be pre listed */
+int authenticate_client_middleware(int sockfd, int *pid)
+{
+       int retval = SECURITY_SERVER_ERROR_AUTHENTICATION_FAILED;
+       struct ucred cr;
+       unsigned int cl = sizeof(cr);
+       char *cmdline = NULL;
+
+       *pid = 0;
+
+       /* get PID of socket peer */
+       if(getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cr, &cl) != 0)
+       {
+               retval = SECURITY_SERVER_ERROR_SOCKET;
+               SEC_SVR_DBG("%s", "Error on getsockopt");
+               goto error;
+       }
+       
+       /* All middlewares will run as root */
+       if(cr.uid != 0)
+       {
+               retval = SECURITY_SERVER_ERROR_AUTHENTICATION_FAILED;
+               SEC_SVR_DBG("Non root process has called API: %d", cr.uid);
+               goto error;
+       }
+
+       /* Read command line of the PID from proc fs */
+       cmdline = read_cmdline_from_proc(cr.pid);
+       if(cmdline  == NULL)
+       {
+               /* It's weired. no file in proc file system, */
+               retval = SECURITY_SERVER_ERROR_FILE_OPERATION;
+               SEC_SVR_DBG("Error on opening /proc/%d/cmdline", cr.pid);
+               goto error;
+       }
+
+       /* Search cmdline of the peer that is really middleware executable */
+       retval = search_middleware_cmdline(cmdline);
+       *pid = cr.pid;
+
+error:
+       if(cmdline != NULL)
+               free(cmdline);
+
+       return retval;
+}
+
+/* Authenticate the application is middleware daemon
+ * The middleware must run as root and the cmd line must be pre listed */
+int authenticate_developer_shell(int sockfd)
+{
+       int retval = SECURITY_SERVER_ERROR_AUTHENTICATION_FAILED;
+       struct ucred cr;
+       unsigned int cl = sizeof(cr);
+       char *cmdline = NULL;
+
+       /* get PID of socket peer */
+       if(getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cr, &cl) != 0)
+       {
+               retval = SECURITY_SERVER_ERROR_SOCKET;
+               SEC_SVR_DBG("%s", "Error on getsockopt");
+               goto error;
+       }
+       
+       /* All middlewares will run as root */
+       if(cr.uid != SECURITY_SERVER_DEVELOPER_UID)
+       {
+               retval = SECURITY_SERVER_ERROR_AUTHENTICATION_FAILED;
+               SEC_SVR_DBG("Non root process has called API: %d", cr.uid);
+               goto error;
+       }
+
+       /* Read command line of the PID from proc fs */
+       cmdline = read_cmdline_from_proc(cr.pid);
+       if(cmdline  == NULL)
+       {
+               /* It's weired. no file in proc file system, */
+               retval = SECURITY_SERVER_ERROR_FILE_OPERATION;
+               SEC_SVR_DBG("Error on opening /proc/%d/cmdline", cr.pid);
+               goto error;
+       }
+
+       /* Search cmdline of the peer that is really debug tool */
+       if(strncmp(cmdline, SECURITY_SERVER_DEBUG_TOOL_PATH, strlen(SECURITY_SERVER_DEBUG_TOOL_PATH)) != 0)
+       {
+               SEC_SVR_DBG("Error: Wrong cmdline [%s]", cmdline);
+               retval = SECURITY_SERVER_ERROR_AUTHENTICATION_FAILED;
+               goto error;
+       }
+       retval = SECURITY_SERVER_SUCCESS;
+       SEC_SVR_DBG("%s", "Client Authenticated");
+
+error:
+       if(cmdline != NULL)
+               free(cmdline);
+
+       return retval;
+}
+
+int free_argv(char **argv, int argc)
+{
+       int i;
+       if(argv == NULL)
+       {
+               SEC_SVR_DBG("%s", "Cannot free NULL pointer");
+               return SECURITY_SERVER_ERROR_INPUT_PARAM;
+       }
+       for (i=0;i<argc;i++)
+       {
+               if(argv[i] != NULL)
+                       free(argv[i]);
+       }
+       free(argv);
+       return SECURITY_SERVER_SUCCESS;
+}
+
diff --git a/src/server/security-server-cookie.c b/src/server/security-server-cookie.c
new file mode 100644 (file)
index 0000000..6470f31
--- /dev/null
@@ -0,0 +1,557 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "security-server-cookie.h"
+
+/* Delete useless cookie item *
+ * then connect prev and next */
+int free_cookie_item(cookie_list *cookie)
+{
+       if(cookie->path != NULL)
+               free(cookie->path);
+       if(cookie->permissions != NULL)
+               free(cookie->permissions);
+       if(cookie->prev != NULL)
+               cookie->prev->next = cookie->next;
+       if(cookie->next != NULL)
+               cookie->next->prev = cookie->prev;
+       free(cookie);
+       cookie = NULL;
+       return 0;
+}
+
+/* Cut the link of the current cookie item and connect previous link and next line *
+ * That is remove a cookie item *
+ * Returns next cookie item  if exist, NULL for no more cookie item */
+cookie_list *delete_cookie_item(cookie_list *cookie)
+{
+       cookie_list *retval = NULL;
+       if(cookie == NULL)
+       {
+               SEC_SVR_DBG("%s", "Cannot delete null cookie");
+               return retval;
+       }
+
+       /* Reconnect cookie item */
+       if(cookie->next != NULL)
+       {
+               cookie->prev->next = cookie->next;
+               cookie->next->prev = cookie->prev;
+               retval = cookie->next;
+       }
+       else
+       {
+               cookie->prev->next = NULL;
+       }
+       
+       free_cookie_item(cookie);
+       return retval;
+}
+
+cookie_list * garbage_collection(cookie_list *cookie)
+{
+       char path[17];
+       cookie_list *retval = NULL;
+       struct stat statbuf;
+       int ret;
+
+       while(cookie != NULL)
+       {
+               /* Skip default cookie */
+               if(cookie->pid ==0)
+                       return cookie;
+
+               /* Try to find the PID directory from proc fs */
+               snprintf(path, sizeof(path), "/proc/%d", cookie->pid);
+               path[16] = 0;
+               ret = stat(path, &statbuf);
+               if(ret != 0)
+               {
+                       /* If it's not exist, delete the cookie */
+                       if(errno == ENOENT)
+                       {
+                               SEC_SVR_DBG("Garbage found. PID:%d, deleting...", cookie->pid);
+                               cookie = delete_cookie_item(cookie);
+                               continue;
+                       }
+                       else
+                       {
+                               /* Some error occurred */
+                               SEC_SVR_DBG("Error occurred on stat: errno = %d", errno);
+                               return cookie;
+                       }
+               }
+               else
+               {
+                       /* This is not a garbage. returning */
+                       return cookie;
+               }
+
+               cookie = cookie->next;
+       }
+       return retval;
+}
+
+/* Search existing cookie from the cookie list for the client process *
+ * At the same time, it collects garbage cookie which PID is no longer exist and delete them */
+cookie_list *search_existing_cookie(int pid, const cookie_list *c_list)
+{
+       cookie_list *current =(cookie_list *)c_list, *cookie = NULL;
+       char *cmdline = NULL, *debug_cmdline = NULL;
+
+       /* Search from the list */
+       while(current != NULL)
+       {
+               /* print_cookie(current);*/
+               current = garbage_collection(current);
+               if(current == NULL)
+                       break;
+
+               /* PID must be same */
+               if(current->pid == pid)
+               {
+                       /* Found cookie for the pid. Check the cookie is reused by dirrent executable */
+                       /* Check the path of the process */
+                       cmdline = (char*)read_cmdline_from_proc(pid);
+                       if(cmdline == NULL)
+                       {
+                               SEC_SVR_DBG("%s", "cannot read cmdline");
+                               return NULL;
+                       }
+                       /* Check the path is different */
+                       if(strncmp(cmdline, current->path, current->path_len) != 0 || strlen(cmdline) != current->path_len)
+                       {
+                               SEC_SVR_DBG("pid [%d] has been reused by %s. deleting the old cookie.", pid, cmdline);
+                               debug_cmdline = malloc(current->path_len + 1);
+                               if(debug_cmdline == NULL)
+                               {
+                                       SEC_SVR_DBG("%s", "out of memory error");
+                                       return NULL;
+                               }
+                               strncpy(debug_cmdline, current->path, current->path_len);
+                               debug_cmdline[current->path_len] = 0;
+                               SEC_SVR_DBG("[%s] --> [%s]", cmdline, debug_cmdline);
+                               if(debug_cmdline != NULL)
+                               {
+                                       free(debug_cmdline);
+                                       debug_cmdline = NULL;
+                               }
+                               /* Okay. delete current cookie */
+                               current = delete_cookie_item(current);
+                               if(cmdline != NULL)
+                               {
+                                       free(cmdline);
+                                       cmdline = NULL;
+                               }
+                               continue;
+                       }
+                       else
+                       {
+                               SEC_SVR_DBG("%s", "cookie found");
+                               cookie = current;
+                       }
+
+                       if(cmdline != NULL)
+                       {
+                               free(cmdline);
+                               cmdline = NULL;
+                       }
+               }
+               current = current->next;
+       }
+       return cookie;
+}
+
+/* Search existing cookie from the cookie list for matching pid *
+ * Default cookie (meaning PID 0) is not allowed in here */
+cookie_list *search_cookie_from_pid(cookie_list *c_list, int pid)
+{
+       cookie_list *current = (cookie_list *)c_list, *retval = NULL;
+
+       /* Search from the list */
+       while(current != NULL)
+       {
+               /* print_cookie(current);*/
+               /* PID must be same */
+               current = garbage_collection(current);
+               if(current == NULL)
+                       break;
+
+               if(current->pid == pid)
+               {
+                       SEC_SVR_DBG("%s", "cookie has been found");
+                       retval = current;
+                       goto finish;
+               }
+               current = current->next;
+       }
+finish:
+       return retval;
+}
+
+/* Search existing cookie from the cookie list for matching cookie and privilege */
+/* If privilege is 0, just search cookie exists or not */
+cookie_list *search_cookie(const cookie_list *c_list, const unsigned char *cookie, int privilege)
+{
+       cookie_list *current = (cookie_list *)c_list, *retval = NULL;
+       int i;
+
+       /* Search from the list */
+       while(current != NULL)
+       {
+               /* print_cookie(current);*/
+               /* PID must be same */
+               current = garbage_collection(current);
+               if(current == NULL)
+                       break;
+
+               if(memcmp(current->cookie, cookie, SECURITY_SERVER_COOKIE_LEN) == 0)
+               {
+                       SEC_SVR_DBG("%s", "cookie has been found");
+
+                       /* default cookie is for root process which is pid is set to 0 */
+                       if(current->pid == 0 || privilege == 0)
+                       {
+                               retval = current;
+                               goto finish;
+                       }
+                       else
+                       {
+                               for(i=0 ; i < current->permission_len ; i++)
+                               {
+                                       if(privilege == current->permissions[i])
+                                       {
+                                               SEC_SVR_DBG("Found privilege %d", privilege);
+                                               retval = current;
+                                               goto finish;
+                                       }
+                               }
+                       }
+               }
+               current = current->next;
+       }
+finish:
+       return retval;
+}
+
+/* Generage a random stream value of size to cookie *
+ * by reading /dev/uranddom file */
+int generate_random_cookie(unsigned char *cookie, int size)
+{
+       int fd, ret;
+
+               fd = open("/dev/urandom", O_RDONLY);
+               if(fd < 0)
+               {
+                       SEC_SVR_DBG("%s", "Cannot open /dev/urandom");
+                       return SECURITY_SERVER_ERROR_FILE_OPERATION;
+               }
+               ret = read(fd, cookie, size);
+               if(ret < size)
+               {
+                       SEC_SVR_DBG("Cannot read /dev/urandom: %d", ret);
+                       ret = SECURITY_SERVER_ERROR_FILE_OPERATION;
+                       goto error;
+               }
+               close(fd);
+               ret = SECURITY_SERVER_SUCCESS;
+error:
+       if(fd > 0)
+               close(fd);
+       return ret;
+}
+
+/* Create a cookie item from PID */
+cookie_list *create_cookie_item(int pid, cookie_list *c_list)
+{
+       int ret, tempint;
+       cookie_list *added = NULL, *current = NULL;
+       char path[24], *cmdline = NULL;
+       char *buf = NULL, inputed, *tempptr = NULL;
+       char delim[] = ": ", *token = NULL;
+       int *permissions = NULL, perm_num = 1, cnt, i, *tempperm = NULL;
+       FILE *fp = NULL;
+
+       current = search_existing_cookie(pid, c_list);
+       if(current != NULL)
+       {
+               /* There is a cookie for this process already */
+               added = current;
+               SEC_SVR_DBG("%s", "Existing cookie found");
+               goto error;
+       }
+
+       /* Read command line of the PID from proc fs */
+       cmdline = (char *)read_cmdline_from_proc(pid);
+       if(cmdline == NULL)
+       {
+               SEC_SVR_DBG("Error on reading /proc/%d/cmdline", pid);
+               goto error;
+       }
+
+       /*
+        * modified by security part
+        *  - get gid from /etc/group
+        */
+       /* Read group info of the PID from proc fs - /proc/[PID]/status */
+       snprintf(path, sizeof(path), "/proc/%d/status", pid);
+       fp = fopen(path, "r");
+
+       /* Find the line which starts with 'Groups:' */
+       i = 0;
+       
+       while(1)
+       {
+               buf = (char*)malloc(sizeof(char) * 128);
+               if(buf == NULL)
+               {
+                       SEC_SVR_DBG("%s", "Error on malloc()");
+                       goto error;
+               }
+               memset(buf, 0x00, 128);
+               cnt = 128;
+
+               /* get one line from /proc/[PID]/status */
+               while(1)
+               {
+                       tempint = fgetc(fp);
+                       inputed = (char)tempint;
+                       if(tempint == EOF)
+                               goto out_of_while;
+                       else if(inputed == '\n')
+                       {
+                               buf[i] = '\0';
+                               break;
+                       }
+                       else if((i == cnt) && (inputed != '\n'))
+                       {
+                               tempptr = (char*)realloc(buf, sizeof(char) * (i + 128));
+                               if(tempptr == NULL)
+                               {
+                                       SEC_SVR_DBG("%s", "Error on realloc()");
+                                       goto error;
+                               }
+                               buf = tempptr;
+                               buf[i++] = inputed;
+                               cnt = i + 128;
+                       }
+                       else
+                               buf[i++] = inputed;
+               }
+               i = 0;
+
+               /* find 'Groups:' */
+               if(strncmp(buf, "Groups:", 7) == 0)
+               {
+                       /* get gid from the line and insert to 'permissions' array */
+                       token = strtok(buf, delim); // first string is "Groups"
+                       while((token = strtok(NULL, delim)))
+                       {
+                               tempperm = realloc(permissions, sizeof(int) * perm_num);
+                               if(tempperm == NULL)
+                               {
+                                       SEC_SVR_DBG("%s", "Error on realloc()");
+                                       goto error;
+                               }
+                               permissions = tempperm;
+                               errno = 0;
+                               permissions[perm_num - 1] = strtoul(token, 0, 10);
+                               if (errno != 0)
+                               {
+                                       SEC_SVR_DBG("cannot change string to integer [%s]", token);
+                                       ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
+                                       goto error;
+                               }
+                               perm_num++;
+                       }
+                       perm_num--;
+
+                       /* goto out of while loop */
+                       break;
+               }
+               if(buf != NULL)
+               {
+                       free(buf);
+                       buf = NULL;
+               }
+       }
+out_of_while:
+               
+       /* Each group ID is stored in each line of the file */
+//     while(fgets(permline, sizeof(permline), fp) != NULL)
+//     {
+//             permissions = realloc(permissions, sizeof(int) * perm_num);
+//             if(permissions == NULL)
+//             {
+//                     SEC_SVR_DBG("%s", "Error on realloc()");
+//                     goto error;
+//             }
+//             permissions[perm_num -1] = strtoul(permline, 0, 10);
+//             perm_num++;
+//     }
+//     perm_num--;
+       /*
+        * modifying end
+        */
+
+       /* Go to last cookie from the list */
+       current = c_list;
+       while(current->next != NULL)
+       {
+               current = current->next;
+       }
+
+       /* Create a new one and assign values */
+       added = malloc(sizeof(cookie_list));
+       if(added == NULL)
+               goto error;
+
+       ret = generate_random_cookie(added->cookie, SECURITY_SERVER_COOKIE_LEN);
+       if(ret != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("Error on making random cookie: %d", ret);
+               free(added);
+               added = NULL;
+               goto error;
+       }
+
+       added->path_len = strlen(cmdline);
+       added->path = calloc(1, strlen(cmdline));
+       memcpy(added->path, cmdline, strlen(cmdline));
+
+       added->permission_len = perm_num;
+       added->pid = pid;
+       added->permissions = permissions;
+       added->prev = current;
+       current->next = added;
+       added->next = NULL;
+
+error:
+       if(cmdline != NULL)
+               free(cmdline);
+       if(fp != NULL)
+               fclose(fp);
+       if(buf != NULL)
+               free(buf);
+
+       if(added == NULL && permissions != NULL)
+               free(permissions);
+
+       return added;
+}
+
+/* Check stored default cookie, if it's not exist make a new one and store it */
+int check_stored_cookie(unsigned char *cookie, int size)
+{
+       int fd, ret;
+
+       /* First, check the default cookie is stored */
+       fd = open(SECURITY_SERVER_DEFAULT_COOKIE_PATH, O_RDONLY);
+       if(fd < 0)
+       {
+               if(errno != ENOENT)
+               {
+                       SEC_SVR_DBG("Cannot open default cookie. errno=%d", errno);
+                       ret = SECURITY_SERVER_ERROR_FILE_OPERATION;
+                       unlink(SECURITY_SERVER_DEFAULT_COOKIE_PATH);
+               }
+
+               ret = generate_random_cookie(cookie, size);
+
+               /* Save cookie to disk */
+               fd = open(SECURITY_SERVER_DEFAULT_COOKIE_PATH, O_WRONLY | O_CREAT, 0600);
+               if (fd < 0)
+               {
+                       SEC_SVR_DBG("Cannot open default cookie errno=%d", errno);
+                       ret = SECURITY_SERVER_ERROR_FILE_OPERATION;
+                       goto error;
+               }
+               ret = write(fd, cookie, size);
+               if(ret < size)
+               {
+                       SEC_SVR_DBG("%s", "Cannot save default cookie");
+                       ret = SECURITY_SERVER_ERROR_FILE_OPERATION;
+                       goto error;
+               }
+
+               /* Change mod only allow root process to read */
+               ret = fchmod(fd, 0600);
+               if (ret < 0)
+               {
+                       SEC_SVR_DBG("%s", "Cannot chmod default cookie");
+                       ret = SECURITY_SERVER_ERROR_FILE_OPERATION;
+                       goto error;
+               }
+               close(fd);
+               return SECURITY_SERVER_SUCCESS;
+       }
+
+       ret = read (fd, cookie, size);
+       if(ret < size)
+       {
+               SEC_SVR_DBG("Cannot read default cookie errno=%d", errno);
+               ret = SECURITY_SERVER_ERROR_FILE_OPERATION;
+               goto error;
+       }
+       ret = SECURITY_SERVER_SUCCESS;
+
+error:
+       if(fd > 0)
+               close(fd);
+       return ret;
+}
+/* Create a cookie item from PID */
+
+/* Create a default cookie when security server is executed *
+ * Default cookie is for root processes that needs cookie */
+cookie_list *create_default_cookie(void)
+{
+       cookie_list *first = NULL;
+       int ret;
+
+       first = malloc(sizeof(cookie_list));
+
+       ret = check_stored_cookie(first->cookie, SECURITY_SERVER_COOKIE_LEN);
+       if(ret != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("Error on making random cookie: %d", ret);
+               free(first);
+               return NULL;
+       }
+
+       first->path_len = 0;
+       first->permission_len = 0;
+       first->pid = 0;
+       first->path = NULL;
+       first->permissions = NULL;
+       first->prev = NULL;
+       first->next = NULL;
+       return first;
+}
diff --git a/src/server/security-server-main.c b/src/server/security-server-main.c
new file mode 100644 (file)
index 0000000..fe4e755
--- /dev/null
@@ -0,0 +1,1080 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <signal.h>
+#include <pthread.h>
+
+#include "security-server-cookie.h"
+#include "security-server-common.h"
+#include "security-server-password.h"
+#include "security-server-comm.h"
+
+/* Set cookie as a global variable */
+cookie_list *c_list;
+pthread_mutex_t cookie_mutex;
+int thread_status[SECURITY_SERVER_NUM_THREADS];
+struct security_server_thread_param {
+       int client_sockfd;
+       int server_sockfd;
+       int thread_status;
+};
+
+/************************************************************************************************/
+/* Just for test. This code must be removed on release */
+#include "security-server-util.h"
+/************************************************************************************************/
+
+#if 0
+void printhex(unsigned char *data, int size)
+{
+       int i;
+       for(i=0;i<size;i++)
+       {
+               if(data[i] < 0xF)
+                       printf("0");
+
+               printf("%X ", data[i]);
+               if(((i+1) % 16) == 0 && i != 0)
+                       printf("\n");
+       }
+       printf("\n");
+}
+
+void print_cookie(cookie_list *list)
+{
+       int i;
+       printf("%s", "cookie:\n");
+       printhex(list->cookie, SECURITY_SERVER_COOKIE_LEN);
+       printf("path_len: %d\n", list->path_len);
+       printf("permission_len: %d\n", list->permission_len);
+       printf("PID: %d\n", list->pid);
+       printf("path: %s\n", list->path);
+       printf("%s", "permissions: ");
+       for(i=0;i<list->permission_len;i++)
+       {
+               printf("%d ", list->permissions[i]);
+       }
+       printf("%s", "\n");
+       printf("prev: %p\n", list->prev);
+       printf("next: %p\n", list->next);
+}
+#endif
+
+/* Object name is actually name of a Group ID *
+ * This function opens /etc/group file and search group ID and
+ * returns the string */
+int search_object_name(int gid, char *obj, int obj_size)
+{
+       FILE *fp = NULL;
+       char *linebuf = NULL, *token = NULL, *token2, *tempstr = NULL;
+       int ret = 0, tmp_gid, bufsize;
+       fp = fopen("/etc/group", "r");
+       if(fp == NULL)
+       {
+               /* cannot open /etc/group */
+               SEC_SVR_DBG("%s", "Cannot open /etc/group");
+               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+       }
+
+       linebuf = malloc(128);
+       bufsize = 128;
+       if(linebuf == NULL)
+       {
+               ret = SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+               SEC_SVR_DBG("%s", "cannot malloc()");
+               goto error;
+       }
+               
+       bzero(linebuf, bufsize);
+       ret = SECURITY_SERVER_ERROR_NO_SUCH_OBJECT;
+       while(fgets(linebuf, bufsize, fp) != NULL)
+       {
+               while(linebuf[bufsize -2] != 0)
+               {
+                       linebuf[bufsize -1] = (char) fgetc(fp);
+                       tempstr = realloc(linebuf, bufsize + 128);
+                       if(tempstr == NULL)
+                       {
+                               ret = SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+                               goto error;
+                       }
+                       linebuf = tempstr;
+                       bzero(linebuf + bufsize, 128);
+                       fgets(linebuf + bufsize, 128, fp);
+                       bufsize += 128;
+               }
+
+               token = strtok(linebuf, ":");   /* group name */
+               if(token == NULL)
+               {
+                       SEC_SVR_DBG("/etc/group is not valid. cannot find gid: [%s]", linebuf);
+                       ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
+                       goto error;
+               }
+               token2 = strtok(NULL, ":");     /* group password */
+               if(token2== NULL)
+               {
+                       SEC_SVR_DBG("/etc/group is not valid. cannot find gid: [%s]", linebuf);
+                       ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
+                       goto error;
+               }
+               token2 = strtok(NULL, ":");     /* gid */
+               if(token2 == NULL)
+               {
+                       SEC_SVR_DBG("/etc/group is not valid. cannot find gid: [%s]", linebuf);
+                       ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
+                       goto error;
+               }
+
+               errno = 0;
+               tmp_gid = strtoul(token2, 0, 10);
+               if (errno != 0)
+               {
+                       SEC_SVR_DBG("cannot change string to integer [%s]", token2);
+                       ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
+                       goto error;
+               }
+
+               if(tmp_gid == gid)
+               {
+                       /* We found it */
+                       if(strlen(token) > obj_size)
+                       {
+                               ret = SECURITY_SERVER_ERROR_BUFFER_TOO_SMALL;
+                               SEC_SVR_DBG("buffer is too small. %d --> %d", obj_size, strlen(token));
+                               goto error;
+                       }
+                       strncpy(obj, token, strlen(token));
+                       obj[strlen(token)] = 0;
+                       ret = SECURITY_SERVER_SUCCESS;
+                       break;
+               }
+               bzero(linebuf, bufsize);
+       }
+       
+error:
+       if(linebuf != NULL)
+               free(linebuf);
+       if(fp != NULL)
+               fclose(fp);
+       return ret;
+}
+
+/* Search GID from group name *
+ * This function opens /etc/group and search group name by given gid */
+int search_gid(const char *obj)
+{
+       FILE *fp = NULL;
+       char *linebuf = NULL, *token = NULL, *token2, *tempstr = NULL;
+       int ret = SECURITY_SERVER_ERROR_NO_SUCH_OBJECT, tmp_gid, bufsize;
+
+       SEC_SVR_DBG("Searching for object %s", obj);
+
+       fp = fopen("/etc/group", "r");
+       if(fp == NULL)
+       {
+               /* cannot open /etc/group */
+               SEC_SVR_DBG("%s", "cannot open /etc/group");
+               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+       }
+
+       linebuf = malloc(128);
+       bufsize = 128;
+       if(linebuf == NULL)
+       {
+               ret = SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+               SEC_SVR_DBG("%s", "Out Of Memory");
+               goto error;
+       }
+
+       bzero(linebuf, bufsize);
+       while(fgets(linebuf, bufsize, fp) != NULL)
+       {
+               while(linebuf[bufsize -2] != 0 )
+               {
+                       linebuf[bufsize -1] = (char) fgetc(fp);
+                       tempstr = realloc(linebuf, bufsize + 128);
+                       if(tempstr == NULL)
+                       {
+                               ret = SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+                               goto error;
+                       }
+                       linebuf = tempstr;
+                       bzero(linebuf + bufsize, 128);
+                       fgets(linebuf + bufsize, 128, fp);
+                       bufsize += 128;
+               }
+
+               token = strtok(linebuf, ":");   /* group name */
+               token2 = strtok(NULL, ":");     /* group password */
+               token2 = strtok(NULL, ":");     /* gid */
+               if(token2 == NULL)
+               {
+                       SEC_SVR_DBG("/etc/group is not valid. cannot find gid: [%s]", linebuf);
+                       ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
+                       goto error;
+               }
+               errno = 0;
+               tmp_gid = strtoul(token2, 0, 10);
+               if ( errno != 0 )
+               {
+                       SEC_SVR_DBG("cannot change string to integer [%s]", token2);
+                       ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
+                       goto error;
+               }
+
+               if(strcmp(obj, token) == 0)
+               {
+                       /* We found it */
+                       ret = tmp_gid;
+                       SEC_SVR_DBG("GID of %s is found: %d", obj, ret);
+                       break;
+               }
+               bzero(linebuf, bufsize);
+       }
+       
+error:
+       if(linebuf != NULL)
+               free(linebuf);
+       if(fp != NULL)
+               fclose(fp);
+       return ret;
+}
+
+/* Signal handler for processes */
+static void security_server_sig_child(int signo, siginfo_t *info, void *data)
+{
+       int status;
+       pid_t child_pid;
+       pid_t child_pgid;
+       
+       child_pgid = getpgid(info->si_pid);
+       SEC_SVR_DBG("Signal handler: dead_pid=%d, pgid=%d",info->si_pid,child_pgid);
+
+       while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) {
+               if(child_pid == child_pgid)
+                       killpg(child_pgid,SIGKILL);
+       }
+
+       return;
+}
+
+/* Execute a debugging tool by fork() and execve() */
+int execute_debug_tool(int argc, char *const *argv, int server_sockfd, int client_sockfd)
+{
+       int ret, i;
+       SEC_SVR_DBG("%s", "Executing tool");
+
+       ret = fork();
+       if(ret == 0)
+       {
+               close(client_sockfd);
+               close(server_sockfd);
+               setsid();
+
+               for(i=0;i<_NSIG;i++)
+                       signal(i, SIG_DFL);
+
+               ret = execv(argv[0], argv);
+               if(ret == -1)
+               {
+                       SEC_SVR_DBG("Error:Failed to execute [%d]", errno);
+                       exit(-1);
+               }
+       }
+       if(ret < 0)
+       {
+               SEC_SVR_DBG("Error: Failed to fork [%d]", errno);
+               return SECURITY_SERVER_ERROR_SERVER_ERROR;
+       }
+       return SECURITY_SERVER_SUCCESS;
+}
+
+int process_cookie_request(int sockfd)
+{
+       int retval, client_pid, client_uid;
+       cookie_list *created_cookie = NULL;
+
+       /* Authenticate client */
+       retval = authenticate_client_application(sockfd, &client_pid, &client_uid);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("%s", "Client Authentication Failed");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+       /* If client application is root process, just respond default cookie */
+       if( client_uid == 0)
+       {
+               SEC_SVR_DBG("%s", "Requested application is a root process");
+               created_cookie = c_list;
+               if(c_list == NULL)
+               {
+                       SEC_SVR_DBG("%s", "Cannot read default cookie");
+                       goto error;
+               }
+       }
+       else
+       {
+               /* Create a new cookie. or find existing one */
+               pthread_mutex_lock(&cookie_mutex);
+               created_cookie = create_cookie_item(client_pid, c_list);
+               pthread_mutex_unlock(&cookie_mutex);
+               if(created_cookie == NULL)
+               {
+                       SEC_SVR_DBG("%s","Cannot create a cookie");
+                       goto error;
+               }
+       }
+       /* send cookie as response */
+       retval = send_cookie(sockfd, created_cookie->cookie);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+       }
+       SEC_SVR_DBG("%s", "Server: Cookie has been sent to client");
+
+error:
+       return retval;
+}
+
+int process_check_privilege_request(int sockfd)
+{
+       /* Authenticate client */
+       int retval, client_pid, requested_privilege;
+       unsigned char requested_cookie[SECURITY_SERVER_COOKIE_LEN];
+       cookie_list *search_result = NULL;
+
+       retval = authenticate_client_middleware(sockfd, &client_pid);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("%s", "Client Authentication Failed");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;;
+       }
+
+       retval = recv_check_privilege_request(sockfd, 
+                               requested_cookie, &requested_privilege);
+       if(retval == SECURITY_SERVER_ERROR_RECV_FAILED)
+       {
+               SEC_SVR_DBG("%s", "Receiving request failed");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;;
+       }
+
+       if(requested_privilege < 1)
+       {
+               SEC_SVR_DBG("Requiring bad privilege [%d]", requested_privilege);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Search cookie list */
+       pthread_mutex_lock(&cookie_mutex);
+       search_result = search_cookie(c_list, requested_cookie, requested_privilege);
+       pthread_mutex_unlock(&cookie_mutex);
+       if(search_result != NULL)
+       {
+               /* We found */
+               SEC_SVR_DBG("We found the cookie with %d privilege and pid:%d", requested_privilege, client_pid);
+               SEC_SVR_DBG("%s", "Cookie comparison succeeded. Access granted.");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_RESPONSE, 
+                               SECURITY_SERVER_RETURN_CODE_ACCESS_GRANTED);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+       }
+       else
+       {
+               /* It's not exist */
+               SEC_SVR_DBG("Could not find the cookie with %d privilege", requested_privilege);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_RESPONSE, 
+                               SECURITY_SERVER_RETURN_CODE_ACCESS_DENIED);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+       }
+error:
+       return retval;
+}
+
+int process_object_name_request(int sockfd)
+{
+       int retval, client_pid, requested_privilege;
+       char object_name[SECURITY_SERVER_MAX_OBJ_NAME];
+
+       /* Authenticate client */
+       retval = authenticate_client_middleware(sockfd, &client_pid);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("%s", "Client Authentication Failed");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_OBJECT_NAME_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Receive GID */
+       retval = read(sockfd, &requested_privilege, sizeof(requested_privilege));
+       if (retval < sizeof(requested_privilege))
+       {
+               SEC_SVR_DBG("%s", "Receiving request failed");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_OBJECT_NAME_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Search from /etc/group */
+       retval = search_object_name(requested_privilege, 
+                       object_name, 
+                       SECURITY_SERVER_MAX_OBJ_NAME);
+       if (retval == SECURITY_SERVER_ERROR_NO_SUCH_OBJECT)
+       {
+               /* It's not exist */
+               SEC_SVR_DBG("There is no such object for gid [%d]", requested_privilege);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_OBJECT_NAME_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_NO_SUCH_OBJECT);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error occurred */
+               SEC_SVR_DBG("Error on searching object name [%d]", retval);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_OBJECT_NAME_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* We found */
+       SEC_SVR_DBG("We found object: %s", object_name);
+       retval = send_object_name(sockfd, object_name);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+       }
+
+error:
+       return retval;
+}
+
+int process_gid_request(int sockfd, int msg_len)
+{
+       int retval, client_pid;
+       char object_name[SECURITY_SERVER_MAX_OBJ_NAME];
+       /* Authenticate client as middleware daemon */
+       retval = authenticate_client_middleware(sockfd, &client_pid);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("%s", "Client authentication failed");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_GID_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       if(msg_len > SECURITY_SERVER_MAX_OBJ_NAME)
+       {
+               /* Too big ojbect name */
+               SEC_SVR_DBG("%s", "Object name is too big");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_GID_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Receive group name */
+       retval = read(sockfd, object_name, msg_len);
+       if (retval < msg_len )
+       {
+               SEC_SVR_DBG("%s", "Failed to read object name");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_GID_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+       object_name[msg_len] = 0;
+
+       /* Search /etc/group for the given group name */
+       retval = search_gid(object_name);
+       if (retval == SECURITY_SERVER_ERROR_NO_SUCH_OBJECT)
+       {
+               /* Not exist */
+               SEC_SVR_DBG("The object [%s] is not exist", object_name);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_GID_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_NO_SUCH_OBJECT);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+       
+       if(retval < 0)
+       {
+               /* Error occurred */
+               SEC_SVR_DBG("Cannot send the response. %d", retval);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_GID_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+
+               goto error;
+       }
+       /* We found */
+       retval = send_gid(sockfd, retval);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("ERROR: Cannot gid response: %d", retval);
+       }
+error:
+       return retval;
+}
+
+int process_pid_request(int sockfd)
+{
+       int retval, client_pid;
+       unsigned char requested_cookie[SECURITY_SERVER_COOKIE_LEN];
+       cookie_list *search_result = NULL;
+
+       /* Authenticate client */
+       retval = authenticate_client_middleware(sockfd, &client_pid);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("%s", "Client Authentication Failed");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_PID_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       retval = recv_pid_request(sockfd, requested_cookie);
+       if(retval == SECURITY_SERVER_ERROR_RECV_FAILED)
+       {
+               SEC_SVR_DBG("%s", "Receiving request failed");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_PID_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Search cookie list */
+       pthread_mutex_lock(&cookie_mutex);
+       search_result = search_cookie(c_list, requested_cookie, 0);
+       pthread_mutex_unlock(&cookie_mutex);
+       if(search_result != NULL)
+       {
+               /* We found */
+               SEC_SVR_DBG("We found the cookie and pid:%d", search_result->pid);
+               SEC_SVR_DBG("%s", "Cookie comparison succeeded. Access granted.");
+               retval = send_pid(sockfd, search_result->pid);
+               
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+       }
+       else
+       {
+               /* It's not exist */
+               SEC_SVR_DBG("%s", "Could not find the cookie");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_PID_RESPONSE, 
+                               SECURITY_SERVER_RETURN_CODE_NO_SUCH_COOKIE);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send pid response: %d", retval);
+               }
+       }
+error:
+       return retval;
+}
+
+int process_tool_request(int client_sockfd, int server_sockfd)
+{
+       int retval, argcnum;
+       char **recved_argv = NULL;
+
+       /* Authenticate client */
+       retval = authenticate_developer_shell(client_sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("%s", "Client Authentication Failed");
+               retval = send_generic_response(client_sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_TOOL_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Receive Total number of argv */
+       argcnum = 0;
+       retval = read(client_sockfd, &argcnum, sizeof(int));
+       if(retval < sizeof(int))
+       {
+               SEC_SVR_DBG("Error: argc recieve failed: %d", retval);
+               retval = send_generic_response(client_sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_TOOL_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+       argcnum += 2;
+       recved_argv = (char **)malloc(sizeof(char *) * argcnum);
+       if(recved_argv == NULL)
+       {
+               SEC_SVR_DBG("Error: malloc() failed: %d", retval);
+               retval = send_generic_response(client_sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_TOOL_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+       memset(recved_argv, 0, sizeof(char *) * argcnum);
+       
+       retval = recv_launch_tool_request(client_sockfd, argcnum -1, recved_argv);
+       if(retval == SECURITY_SERVER_ERROR_RECV_FAILED)
+       {
+               SEC_SVR_DBG("%s", "Receiving request failed");
+               recved_argv = NULL;
+               retval = send_generic_response(client_sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_TOOL_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+       if(argcnum < 2)
+       {
+               SEC_SVR_DBG("Error: Too small number of argv [%d]", argcnum);
+               retval = send_generic_response(client_sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_TOOL_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+       /* Execute the command */
+       retval = execute_debug_tool(argcnum, recved_argv, server_sockfd, client_sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("Error: Cannot execute debug tool [%d]", retval);
+               retval = send_generic_response(client_sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_TOOL_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+       }
+       else
+       {
+               SEC_SVR_DBG("%s", "Tool has been executed");
+               retval = send_generic_response(client_sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_TOOL_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_SUCCESS);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+       }
+error:
+       if(recved_argv != NULL)
+       {
+               /* Free */
+               free_argv(recved_argv, argcnum);
+               recved_argv = NULL;
+               argcnum =0;;
+       }
+       return retval;
+}
+
+void *security_server_thread(void *param)
+{
+       int client_sockfd = -1, client_uid, client_pid;
+       int server_sockfd, retval, argcnum;
+       basic_header basic_hdr;
+       struct security_server_thread_param *my_param;
+
+       my_param = (struct security_server_thread_param *) param;
+       client_sockfd = my_param->client_sockfd;
+       server_sockfd = my_param->server_sockfd;
+
+       /* Receive request header */
+       retval = recv_hdr(client_sockfd, &basic_hdr);
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT || retval == SECURITY_SERVER_ERROR_RECV_FAILED
+               || retval == SECURITY_SERVER_ERROR_SOCKET)
+       {
+               SEC_SVR_DBG("Receiving header error [%d]",retval);
+               close(client_sockfd);
+               client_sockfd = -1;
+               goto error;;
+       }
+
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Response */
+               SEC_SVR_DBG("Receiving header error [%d]",retval);
+               retval = send_generic_response(client_sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+                       goto error;
+               }
+               safe_server_sock_close(client_sockfd);
+               client_sockfd = -1;
+               goto error;
+       }
+
+       /* Act different for request message ID */
+       switch(basic_hdr.msg_id)
+       {
+               case SECURITY_SERVER_MSG_TYPE_COOKIE_REQUEST:
+                       SEC_SVR_DBG("%s", "Cookie request received");
+                       process_cookie_request(client_sockfd);
+                       break;
+
+               case SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_REQUEST:
+                       SEC_SVR_DBG("%s", "Privilege check received");
+                       process_check_privilege_request(client_sockfd);
+                       break;
+
+               case SECURITY_SERVER_MSG_TYPE_OBJECT_NAME_REQUEST:
+                       SEC_SVR_DBG("%s", "Get object name request received");
+                       process_object_name_request(client_sockfd);
+                       break;
+
+               case SECURITY_SERVER_MSG_TYPE_GID_REQUEST:
+                       SEC_SVR_DBG("%s", "Get GID received");
+                       process_gid_request(client_sockfd, (int)basic_hdr.msg_len);
+                       break;
+
+               case SECURITY_SERVER_MSG_TYPE_PID_REQUEST:
+                       SEC_SVR_DBG("%s", "pid request received");
+                       process_pid_request(client_sockfd);
+                       break;
+
+               case SECURITY_SERVER_MSG_TYPE_TOOL_REQUEST:
+                       SEC_SVR_DBG("%s", "launch tool request received");
+                       process_tool_request(client_sockfd, server_sockfd);
+                       break;
+
+               case SECURITY_SERVER_MSG_TYPE_VALID_PWD_REQUEST:
+                       SEC_SVR_DBG("%s", "Server: validate password request received");
+                       process_valid_pwd_request(client_sockfd);
+                       break;
+                       
+               case SECURITY_SERVER_MSG_TYPE_SET_PWD_REQUEST:
+                       SEC_SVR_DBG("%s", "Server: set password request received");
+                       process_set_pwd_request(client_sockfd);
+                       break;
+
+               case SECURITY_SERVER_MSG_TYPE_RESET_PWD_REQUEST:
+                       SEC_SVR_DBG("%s", "Server: reset password request received");
+                       process_reset_pwd_request(client_sockfd);
+                       break;
+
+               case SECURITY_SERVER_MSG_TYPE_CHK_PWD_REQUEST:
+                       SEC_SVR_DBG("%s", "Server: check password request received");
+                       process_chk_pwd_request(client_sockfd);
+                       break;
+
+               case SECURITY_SERVER_MSG_TYPE_SET_PWD_HISTORY_REQUEST:
+                       SEC_SVR_DBG("%s", "Server: set password histroy request received");
+                       process_set_pwd_history_request(client_sockfd);
+                       break;
+/************************************************************************************************/
+/* Just for test. This code must be removed on release */
+               case SECURITY_SERVER_MSG_TYPE_GET_ALL_COOKIES_REQUEST:
+                       SEC_SVR_DBG("%s", "all cookie info request received -- NEED TO BE DELETED ON RELEASE");
+                       retval = authenticate_client_application(client_sockfd, &client_pid, &client_uid);
+                       if(retval != SECURITY_SERVER_SUCCESS)
+                       {
+                               SEC_SVR_DBG("%s", "Client Authentication Failed");
+                               retval = send_generic_response(client_sockfd, 
+                                               SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE,
+                                               SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
+                               if(retval != SECURITY_SERVER_SUCCESS)
+                               {
+                                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+                               }
+                               break;
+                       }
+                       retval = util_process_all_cookie(client_sockfd, c_list);
+                       if(retval != SECURITY_SERVER_SUCCESS)
+                       {
+                               SEC_SVR_DBG("ERROR: Cannot send all cookie info: %d", retval);
+                       }
+                       break;
+
+               case SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_FROM_PID_REQUEST:
+                       SEC_SVR_DBG("%s", "cookie info from pid request received -- NEED TO BE DELETED ON RELEASE");
+                       if(retval != SECURITY_SERVER_SUCCESS)
+                       {
+                               SEC_SVR_DBG("%s", "Client Authentication Failed");
+                               retval = send_generic_response(client_sockfd, 
+                                               SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE,
+                                               SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
+                               if(retval != SECURITY_SERVER_SUCCESS)
+                               {
+                                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+                               }
+                               break;
+                       }
+                       util_process_cookie_from_pid(client_sockfd, c_list);
+                       break;
+
+               case SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_FROM_COOKIE_REQUEST:
+                       SEC_SVR_DBG("%s", "cookie info from cookie request received -- NEED TO BE DELETED ON RELEASE");
+                       if(retval != SECURITY_SERVER_SUCCESS)
+                       {
+                               SEC_SVR_DBG("%s", "Client Authentication Failed");
+                               retval = send_generic_response(client_sockfd, 
+                                               SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE,
+                                               SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
+                               if(retval != SECURITY_SERVER_SUCCESS)
+                               {
+                                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+                               }
+                               break;
+                       }
+                       util_process_cookie_from_cookie(client_sockfd, c_list);
+                       break;
+/************************************************************************************************/
+
+
+               default:
+                       SEC_SVR_DBG("Unknown msg ID :%d", basic_hdr.msg_id);
+                       /* Unknown message ID */
+                       retval = send_generic_response(client_sockfd, 
+                       SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE,
+                       SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+                       if(retval != SECURITY_SERVER_SUCCESS)
+                       {
+                               SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+                       }
+                       break;
+       }
+
+       if(client_sockfd > 0)
+       {
+               safe_server_sock_close(client_sockfd);
+               client_sockfd = -1;
+       }
+
+error:
+       if(client_sockfd > 0)
+               close(client_sockfd);
+       thread_status[my_param->thread_status] = 0;
+       pthread_detach(pthread_self());
+       pthread_exit(NULL);
+}
+
+
+
+int main(int argc, char* argv[])       
+{
+       int server_sockfd = 0, retval, client_sockfd = -1, args[2], rc;
+       struct sigaction act, dummy;
+       pthread_t threads[SECURITY_SERVER_NUM_THREADS];
+       struct security_server_thread_param param[SECURITY_SERVER_NUM_THREADS];
+
+       SEC_SVR_DBG("%s", "Starting Security Server");
+
+       /* security server must be executed by root */
+       if(getuid() != 0)
+       {
+               fprintf(stderr, "%s\n", "You are not root. exiting...");
+               goto error;
+       }
+
+       for(retval = 0 ; retval < SECURITY_SERVER_NUM_THREADS; retval++)
+               thread_status[retval] = 0;
+       int initiate_try();
+
+       /* Create and bind a Unix domain socket */
+       retval = create_new_socket(&server_sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("%s", "cannot create socket. exiting...");
+               goto error;
+       }
+
+       if(listen(server_sockfd, 5) < 0)
+       {
+               SEC_SVR_DBG("%s", "listen() failed. exiting...");
+               goto error;
+       }
+
+       /* Create a default cookie --> Cookie for root process */
+       c_list = create_default_cookie();
+       if(c_list == NULL)
+       {
+               SEC_SVR_DBG("%s", "cannot make a default cookie. exiting...");
+               goto error;
+       }
+
+       /* Init signal handler */
+       act.sa_handler = NULL;
+       act.sa_sigaction = security_server_sig_child;
+       sigemptyset(&act.sa_mask);
+       act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
+
+       if (sigaction(SIGCHLD, &act, &dummy) < 0)
+       {
+               SEC_SVR_DBG("%s", "cannot change session");
+       }
+       
+       pthread_mutex_init(&cookie_mutex, NULL);
+
+       while(1)
+       {
+               /* Accept a new client */
+               if(client_sockfd < 0)
+                       client_sockfd = accept_client(server_sockfd);
+               
+               if(client_sockfd == SECURITY_SERVER_ERROR_TIMEOUT)
+                       continue;
+               if(client_sockfd < 0)
+                       goto error;
+               SEC_SVR_DBG("Server: new connection has been accepted: %d", client_sockfd);
+               retval = 0;
+               while(1)
+               {
+                       if(thread_status[retval] == 0)
+                       {
+                               thread_status[retval] = 1;
+                               param[retval].client_sockfd = client_sockfd;
+                               param[retval].server_sockfd = server_sockfd;
+                               param[retval].thread_status= retval;
+                               SEC_SVR_DBG("Server: Creating a new thread: %d", retval);
+                               rc =pthread_create(&threads[retval], NULL, security_server_thread, (void *)&param[retval]);
+                               if (rc)
+                               {
+                                       SEC_SVR_DBG("Error: Server: Cannot create thread:%d", rc);
+                                       goto error;
+                               }
+                               break;
+                       }
+                       retval++;
+                       if(retval >= SECURITY_SERVER_NUM_THREADS)
+                               retval = 0;
+               }
+               client_sockfd = -1;
+       }
+error:
+       if(server_sockfd > 0)
+               close(server_sockfd);
+       pthread_exit(NULL);
+       return 0;
+}
diff --git a/src/server/security-server-password.c b/src/server/security-server-password.c
new file mode 100644 (file)
index 0000000..ff84c64
--- /dev/null
@@ -0,0 +1,1411 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <openssl/sha.h>
+
+#include "security-server-password.h"
+
+struct timeval prev_try;
+
+int initiate_try()
+{
+       gettimeofday(&prev_try, NULL);
+}
+
+int validate_pwd_file(char *filename)
+{
+       int i;
+
+       if((strncmp(filename + (strlen(filename) -4), ".pwd" , 4)) != 0)
+       {
+               SEC_SVR_DBG("The passwor filename [%s] is invalid", filename);
+               return SECURITY_SERVER_ERROR_NO_PASSWORD;
+       }
+
+       for(i=0;i<(strlen(filename) -4);i++)
+       {
+               if(filename[i] > '9' || filename[i] < '0')
+               {
+                       SEC_SVR_DBG("The passwor filename [%s] is invalid", filename);
+                       return SECURITY_SERVER_ERROR_NO_PASSWORD;
+               }
+       }
+       return SECURITY_SERVER_SUCCESS;
+}
+
+int dir_filter(const struct dirent *entry)
+{
+       if ((strcmp(entry->d_name, ".") == 0) || 
+               (strcmp(entry->d_name, "..") == 0) ||
+               (strcmp(entry->d_name, "attempts") ==0) ||
+               (strcmp(entry->d_name, "history") ==0) )
+               return (0);
+       else
+               return (1);
+}
+
+int get_pwd_path(char *path)
+{
+       int retval;
+       struct dirent **mydirent;
+       int num;
+       num = scandir(SECURITY_SERVER_DATA_DIRECTORY_PATH, &mydirent, &dir_filter, alphasort);
+       if(num < 0)
+       {
+               SEC_SVR_DBG("Server: [Error] Cannot scan password directory. errno: %d", errno);
+               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+       }
+       if(num == 0)
+       {
+               SEC_SVR_DBG("%s", "Server: There is no password file");
+               return SECURITY_SERVER_ERROR_NO_PASSWORD;
+       }
+
+       snprintf(path, 255, "%s/%s", SECURITY_SERVER_DATA_DIRECTORY_PATH, mydirent[num-1]->d_name);
+       retval = validate_pwd_file(mydirent[num-1]->d_name);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("Removing invalid password file: %s", path);
+               unlink(path);
+               get_pwd_path(path);
+       }
+       SEC_SVR_DBG("Password file path: %s", path);
+       while (num--)
+               free(mydirent[num]);
+       free(mydirent);
+       return SECURITY_SERVER_SUCCESS;
+}
+       
+int load_password(unsigned char *cur_pwd, unsigned int *max_attempt, unsigned int *expire_time)
+{
+       int retval, fd;
+       char pwd_path[255];
+
+       /* Create directory */
+       retval = mkdir(SECURITY_SERVER_DATA_DIRECTORY_PATH, 0700);
+       if(retval != 0)
+       {
+               if(errno != EEXIST)
+               {
+                       SEC_SVR_DBG("Cannot create directory. errno: %d", errno);
+                       return SECURITY_SERVER_ERROR_FILE_OPERATION;
+               }
+       }
+
+       /* Check password files */
+       while(1)
+       {
+               /* Get password file path */
+               retval = get_pwd_path(pwd_path);
+               if(retval == SECURITY_SERVER_ERROR_NO_PASSWORD)
+               {
+                       SEC_SVR_DBG("%s", "Current password doesn't exist");
+                       return SECURITY_SERVER_ERROR_NO_PASSWORD;
+               }
+
+               /* Load password file */
+               fd = open(pwd_path, O_RDONLY | O_NONBLOCK );
+               if(fd < 0)
+               {
+                       if(errno == ENOENT)
+                       {
+                               SEC_SVR_DBG("%s", "Server: Current password doesn't exist");
+                               return SECURITY_SERVER_ERROR_NO_PASSWORD;
+                       }
+                       SEC_SVR_DBG("Server: Current password cannot be opened. errno: %d", errno);
+                       return SECURITY_SERVER_ERROR_FILE_OPERATION;
+               }
+
+               /* Read and store into memory */
+               retval = read(fd, cur_pwd, SECURITY_SERVER_HASHED_PWD_LEN);
+               if(retval < SECURITY_SERVER_HASHED_PWD_LEN)
+               {
+                       SEC_SVR_DBG("%s", "Server: Current password corrupted. resetting to previous one. 0");
+                       close(fd);
+                       fd = 0;
+                       unlink(pwd_path);
+                       continue;
+               }
+
+               retval = read(fd, max_attempt, sizeof(unsigned int));
+               if(retval < sizeof(unsigned int))
+               {
+                       SEC_SVR_DBG("%s", "Server: Current password corrupted. resetting to previous one. 1");
+                       close(fd);
+                       fd = 0;
+                       unlink(pwd_path);
+                       continue;
+               }
+
+               retval = read(fd, expire_time, sizeof(unsigned int));
+               if(retval < sizeof(unsigned int))
+               {
+                       SEC_SVR_DBG("%s", "Server: Current password corrupted. resetting to previous one. 2");
+                       close(fd);
+                       fd = 0;
+                       unlink(pwd_path);
+                       continue;
+               }
+               close(fd);
+
+               /* Check expiration time. */
+               if(*expire_time == 0)  /* No valid period */
+                       *expire_time = 0xffffffff;
+               else if(*expire_time <= time(NULL)) /* expired */
+                       *expire_time =0;
+               else            /* valid yet */
+                       *expire_time -= time(NULL);
+               break;
+       }
+       SEC_SVR_DBG("%s", "Server: Current password file successfully loaded");
+       return SECURITY_SERVER_SUCCESS;
+}
+
+int get_current_attempt(int increase)
+{
+       int retval, fd, attempt;
+       char path[255];
+
+       snprintf(path, 255, "%s/%s", SECURITY_SERVER_DATA_DIRECTORY_PATH,
+               SECURITY_SERVER_ATTEMPT_FILE_NAME);
+
+       /* Open current attempt file as read mode */
+       fd = open(path, O_RDONLY | O_NONBLOCK );
+       if(fd < 0)
+       {
+               if(errno == ENOENT)
+               {
+                       SEC_SVR_DBG("%s", "Server: attempt doesn't exist. Creating one:");
+                       /* Create one if it doesn't exist */
+                       fd = open(path, O_WRONLY | O_NONBLOCK | O_CREAT, 0600);
+                       if(fd < 0)
+                       {
+                               SEC_SVR_DBG("Server ERROR: Cannot open attempt file. errno: %d", errno);
+                               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+                       }
+                       retval = fchmod(fd, 0600);
+                       if(retval != 0)
+                       {
+                               SEC_SVR_DBG("Server ERROR: Cannot chmod attempt file. errno: %d", errno);
+                               close(fd);
+                               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+                       }
+                       attempt = increase;
+                       retval = write(fd, &attempt, sizeof(int));
+                       close(fd);
+                       if(retval < sizeof(int))
+                       {
+                               SEC_SVR_DBG("%s", "Server ERROR: Cannot write attempt");
+                               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+                       }
+                       return attempt;
+               }
+               SEC_SVR_DBG("Current password cannot be opened. errno: %d", errno);
+               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+       }
+       retval = read(fd, &attempt, sizeof(int));
+       close(fd);
+       if(retval < sizeof(int))
+       {
+               SEC_SVR_DBG("%s", "Server ERROR: Cannot read attempt");
+               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+       }
+
+       if(increase > 0)
+       {
+               /* Open the file again with write mode */
+               fd = open(path, O_WRONLY | O_NONBLOCK, 0600);
+               if(fd < 0)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot open attempt file. errno: %d", errno);
+                       return SECURITY_SERVER_ERROR_FILE_OPERATION;
+               }
+               retval = fchmod(fd, 0600);
+               if(retval != 0)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot chmod attempt file. errno: %d", errno);
+                       close(fd);
+                       return SECURITY_SERVER_ERROR_FILE_OPERATION;
+               }
+               attempt += increase;
+               retval = write(fd, &attempt, sizeof(int));
+               close(fd);
+               if(retval < sizeof(int))
+               {
+                       SEC_SVR_DBG("%s", "Server ERROR: Cannot write attempt");
+                       return SECURITY_SERVER_ERROR_FILE_OPERATION;
+               }
+       }
+       return attempt;         
+}
+
+int reset_attempt(void)
+{
+       int fd, retval;
+       char path[255];
+       unsigned int attempt = 0;
+
+       snprintf(path, 255, "%s/%s", SECURITY_SERVER_DATA_DIRECTORY_PATH,
+               SECURITY_SERVER_ATTEMPT_FILE_NAME);
+
+       /* Open the file again with write mode */
+       fd = open(path, O_WRONLY | O_NONBLOCK, 0600);
+       if(fd < 0)
+       {
+               SEC_SVR_DBG("Server ERROR: Cannot open attempt file. errno: %d", errno);
+               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+       }
+       retval = fchmod(fd, 0600);
+       if(retval != 0)
+       {
+               SEC_SVR_DBG("Server ERROR: Cannot chmod attempt file. errno: %d", errno);
+               close(fd);
+               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+       }
+       retval = write(fd, &attempt, sizeof(int));
+       close(fd);
+       if(retval < sizeof(int))
+       {
+               SEC_SVR_DBG("%s", "Server ERROR: Cannot write attempt");
+               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+       }
+       SEC_SVR_DBG("%s", "Server: Attempt reset");
+       return SECURITY_SERVER_SUCCESS;
+}
+
+/* Compare current password Stored password is hashed by SHA-256 Algorithm */
+int check_password(const unsigned char *cur_pwd, const unsigned char *requested_pwd,
+                       const unsigned int max_attempts, const unsigned int expire_time,
+                       int *current_attempt)
+{
+       unsigned int current_time;
+
+       if(max_attempts != 0)
+       {
+               *current_attempt = get_current_attempt(1);
+
+               if(*current_attempt > max_attempts)
+               {
+                       SEC_SVR_DBG("Server: Max attempt exceeded: %d, %d", *current_attempt, max_attempts);
+                       return SECURITY_SERVER_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED;
+               }
+               if(*current_attempt < 0)
+               {
+                       SEC_SVR_DBG("Server: Attempt file operation failed. Ignoring... : %d", *current_attempt);
+               }
+       }
+
+       if(expire_time == 0)
+       {
+               SEC_SVR_DBG("Server: Password has been expired: %d, %d", current_time, expire_time);
+               return SECURITY_SERVER_ERROR_PASSWORD_EXPIRED;
+       }
+
+       /* Compare */
+       if(memcmp(cur_pwd, requested_pwd, SECURITY_SERVER_HASHED_PWD_LEN) == 0)
+       {
+               SEC_SVR_DBG("%s", "Password matched");
+               return SECURITY_SERVER_SUCCESS;
+       }
+       SEC_SVR_DBG("%s", "Password mismatched");
+       return SECURITY_SERVER_ERROR_PASSWORD_MISMATCH;
+}
+
+int set_history(int num)
+{
+       int fd, retval;
+       char path[255];
+
+       snprintf(path, 255, "%s/%s", SECURITY_SERVER_DATA_DIRECTORY_PATH,
+               SECURITY_SERVER_HISTORY_FILE_NAME);
+
+       /* Open the file again with write mode */
+       fd = open(path, O_WRONLY | O_NONBLOCK, 0600);
+       if(fd < 0)
+       {
+               if (errno == ENOENT)
+               {
+                       fd = open(path, O_WRONLY | O_NONBLOCK | O_CREAT, 0600);
+                       if(fd < 0)
+                       {
+                               SEC_SVR_DBG("Server ERROR: Cannot create history file. errno: %d", errno);
+                               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+                       }
+               }
+               else
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot open history file. errno: %d", errno);
+                       return SECURITY_SERVER_ERROR_FILE_OPERATION;
+               }
+       }
+       retval = fchmod(fd, 0600);
+       if(retval != 0)
+       {
+               SEC_SVR_DBG("Server ERROR: Cannot chmod history file. errno: %d", errno);
+               close(fd);
+               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+       }
+       retval = write(fd, &num, sizeof(int));
+       close(fd);
+       if(retval < sizeof(int))
+       {
+               SEC_SVR_DBG("%s", "Server ERROR: Cannot write history");
+               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+       }
+       SEC_SVR_DBG("%s", "Server: history set finished");
+       return SECURITY_SERVER_SUCCESS;
+}
+               
+
+int get_history_num(void)
+{
+       /* Placeholder for password history check count getting function */
+       int fd, retval, history;
+       char path[255];
+
+       snprintf(path, 255, "%s/%s", SECURITY_SERVER_DATA_DIRECTORY_PATH,
+               SECURITY_SERVER_HISTORY_FILE_NAME);
+
+       /* Load password file */
+       fd = open(path, O_RDONLY | O_NONBLOCK );
+       if(fd < 0)
+       {
+               if(errno == ENOENT)
+               {
+                       SEC_SVR_DBG("%s", "Server: history file doesn't exist");
+                       retval = set_history(0);
+                       return retval;
+               }
+               SEC_SVR_DBG("Server ERROR: history file cannot be opened. errno: %d", errno);
+               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+       }
+       retval = read(fd, &history, sizeof(history));
+       close(fd);
+       if(retval < sizeof(history))
+       {
+               SEC_SVR_DBG("%s", "History file corrupted. Creating new one");
+               unlink(path);
+               retval = set_history(0);
+               return retval;
+       }
+       SEC_SVR_DBG("History file read: %d", history);
+       return history;
+}
+
+
+
+int check_history(const unsigned char *requested_pwd)
+{
+       unsigned char history_pwd[SECURITY_SERVER_HASHED_PWD_LEN];
+       char path[255];
+       unsigned int max_history;
+       int num, history_count, fd, file_count, retval;
+       int retval2 = SECURITY_SERVER_SUCCESS;
+       struct dirent **mydirent;
+
+       history_count = get_history_num();
+       if(history_count <= 0)
+               return SECURITY_SERVER_SUCCESS;
+
+       num = scandir(SECURITY_SERVER_DATA_DIRECTORY_PATH, &mydirent, &dir_filter, alphasort);
+       if(num < 0)
+       {
+               SEC_SVR_DBG("Server: [Error] Cannot scan password directory. errno: %d", errno);
+               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+       }
+
+       if(num == 0)
+       {
+               SEC_SVR_DBG("%s", "Server: There is no password file");
+               return SECURITY_SERVER_ERROR_NO_PASSWORD;
+       }
+
+       file_count = 2;
+       while((num--))
+       {
+               snprintf(path, 255, "%s/%s", SECURITY_SERVER_DATA_DIRECTORY_PATH, mydirent[num]->d_name);
+               SEC_SVR_DBG("Password file path: %s", path);
+               if(history_count > 0)
+               {
+                       /* Load password file */
+                       fd = open(path, O_RDONLY | O_NONBLOCK );
+                       if(fd < 0)
+                       {
+                               if(errno == ENOENT)
+                               {
+                                       SEC_SVR_DBG("%s", "Current password doesn't exist");
+                                       return SECURITY_SERVER_SUCCESS;
+                               }
+                               SEC_SVR_DBG("Current password cannot be opened. errno: %d", errno);
+                               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+                       }
+                       /* Read and store into memory */
+                       retval = read(fd, history_pwd, SECURITY_SERVER_HASHED_PWD_LEN);
+                       if(retval < SECURITY_SERVER_HASHED_PWD_LEN)
+                       {
+                               SEC_SVR_DBG("%s", "Current password corrupted. resetting to previous one. 0");
+                               close(fd);
+                               fd = 0;
+                               unlink(path);
+                               continue;
+                       }
+                       close(fd);
+                       /* Compare */
+                       if(memcmp(history_pwd, requested_pwd, SECURITY_SERVER_HASHED_PWD_LEN) == 0)
+                       {
+                               SEC_SVR_DBG("%s", "Server: Password has been reused");
+                               retval2 =  SECURITY_SERVER_ERROR_PASSWORD_REUSED;
+                       }
+                       history_count--;
+                       
+               }
+
+               /* Remove too old or invalid password history */
+               retval = validate_pwd_file(mydirent[num]->d_name);
+               if(retval != SECURITY_SERVER_SUCCESS || file_count > (SECURITY_SERVER_MAX_PASSWORD_HISTORY))
+               {
+                       SEC_SVR_DBG("Removing too old password. %s", path);
+                       unlink(path);
+               }
+               file_count++;
+               free(mydirent[num]);
+       }
+       free(mydirent);
+       if(retval2 == SECURITY_SERVER_ERROR_PASSWORD_REUSED)
+               retval = retval2;
+       return retval;
+}
+
+/* Password file format */
+/*  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ * |---------------------------------------------------------------|
+ * |                                                               |
+ * |                                                               |
+ * |                       Hashed PWD (32 bytes)                   |
+ * |                                                               |
+ * |---------------------------------------------------------------|
+ * |                       Max attempts (4 bytes)                  |
+ * |---------------------------------------------------------------|
+ * |              Expiration time in seconds (4 bytes)             |
+ * |---------------------------------------------------------------|
+ */
+int set_password(const unsigned char *requested_new_pwd, const unsigned int attempts, 
+                       const unsigned int expire_time)
+{
+       int retval, fd;
+       char pwd_path[255];
+
+       /* New file created */
+       retval = time(NULL);
+       snprintf(pwd_path, 255, "%s/%d.pwd", SECURITY_SERVER_DATA_DIRECTORY_PATH, retval);
+
+       /* Save new password as current password */
+       fd = open(pwd_path, O_WRONLY | O_NONBLOCK | O_CREAT, 0600);
+       if(fd < 0)
+       {
+               SEC_SVR_DBG("Cannot open current password file. errno: %d", errno);
+               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+       }
+       retval = fchmod(fd, 0600);
+       if(retval != 0)
+       {
+               SEC_SVR_DBG("Cannot chmod current password file. errno: %d", errno);
+               close(fd);
+               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+       }
+       retval = write(fd, requested_new_pwd, SECURITY_SERVER_HASHED_PWD_LEN);
+       if(retval < SECURITY_SERVER_HASHED_PWD_LEN)
+       {
+               SEC_SVR_DBG("%s", "Cannot write password");
+               close(fd);
+               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+       }
+       retval = write(fd, &attempts, sizeof(unsigned int));
+       if(retval < sizeof(unsigned int))
+       {
+               SEC_SVR_DBG("%s", "Cannot write password");
+               close(fd);
+               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+       }
+       retval = write(fd, &expire_time, sizeof(unsigned int));
+       if(retval < sizeof(unsigned int))
+       {
+               SEC_SVR_DBG("%s", "Cannot write password");
+               close(fd);
+               return SECURITY_SERVER_ERROR_FILE_OPERATION;
+       }
+       fsync(fd);
+       close(fd);
+       SEC_SVR_DBG("%s", "Password file created");
+       return SECURITY_SERVER_SUCCESS; 
+}
+
+int check_retry(const struct timeval cur_try)
+{
+       int retval, interval_sec, interval_usec;
+       interval_sec = cur_try.tv_sec - prev_try.tv_sec;
+       interval_usec = cur_try.tv_usec - prev_try.tv_usec;
+       prev_try = cur_try;
+       if(interval_sec > SECURITY_SERVER_PASSWORD_RETRY_TIMEOUT_SECOND)
+               return SECURITY_SERVER_SUCCESS;
+
+       if(interval_sec == SECURITY_SERVER_PASSWORD_RETRY_TIMEOUT_SECOND 
+                       && interval_usec >= 0)
+               return SECURITY_SERVER_SUCCESS;
+
+       SEC_SVR_DBG("%s", "retry timer hit");
+       return SECURITY_SERVER_ERROR_PASSWORD_RETRY_TIMER;
+}
+
+int process_valid_pwd_request(int sockfd)
+{
+       struct timeval cur_try;
+       int retval, current_attempts, password_set;
+       unsigned char cur_pwd[SECURITY_SERVER_HASHED_PWD_LEN];
+       unsigned int max_attempt, expire_time;
+       
+/*     
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("%s", "Client Authentication Failed");
+               retval = send_generic_response(client_sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_TOOL_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+*/
+
+       /* Check retry timer */
+       gettimeofday(&cur_try, NULL);
+       retval = check_retry(cur_try);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("%s", "Server: Retry timeout occurred");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_PASSWORD_RETRY_TIMER);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+       password_set = load_password(cur_pwd, &max_attempt, &expire_time);
+       if(password_set == SECURITY_SERVER_ERROR_SERVER_ERROR)
+       {
+               SEC_SVR_DBG("%s", "Server: Responding error because we cannot provide password service");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       current_attempts = get_current_attempt(0);
+       if(current_attempts < 0)
+       {
+               SEC_SVR_DBG("Server ERROR: Cannot get attempts: %d", current_attempts);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+       }
+
+       /* There is no password */
+       if(password_set == SECURITY_SERVER_ERROR_NO_PASSWORD)
+       {
+               retval = send_pwd_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_VALID_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_NO_PASSWORD, 
+                               0, 0, 0);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send password response: %d", retval);
+               }
+               goto error;
+       }
+       if(password_set == SECURITY_SERVER_SUCCESS)
+       {
+               retval = send_pwd_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_VALID_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_PASSWORD_EXIST,
+                               current_attempts, max_attempt, expire_time);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send password response: %d", retval);
+               }
+               goto error;
+       }
+       SEC_SVR_DBG("Server ERROR: Unknown error: %d", retval);
+       retval = send_generic_response(sockfd, 
+                       SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE,
+                       SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+       }
+error:
+       return retval;
+}
+
+int process_set_pwd_request(int sockfd)
+{
+       struct timeval cur_try;
+       int retval, password_set, current_attempt;
+       unsigned int max_attempt, expire_time, valid_days, received_attempts;
+       char  new_pwd_len = 0, cur_pwd_len = 0;
+       char requested_cur_pwd[SECURITY_SERVER_MAX_PASSWORD_LEN+1];
+       char requested_new_pwd[SECURITY_SERVER_MAX_PASSWORD_LEN+1];
+       unsigned char cur_pwd[SECURITY_SERVER_HASHED_PWD_LEN];
+       unsigned char hashed_challenge[SECURITY_SERVER_HASHED_PWD_LEN];
+       unsigned char hashed_new_pw[SECURITY_SERVER_HASHED_PWD_LEN];
+
+       SHA256_CTX context;
+
+       /* Authenticate client that peer is setting app goes here*/
+       /* Check SMACK 'rw' rule for the set password */
+       retval = SECURITY_SERVER_SUCCESS;
+/*
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("%s", "Client Authentication Failed");
+               retval = send_generic_response(client_sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_TOOL_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+*/
+
+       /* Check retry timer */
+       gettimeofday(&cur_try, NULL);
+       retval = check_retry(cur_try);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("%s", "Server: Retry timeout occurred");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_PASSWORD_RETRY_TIMER);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+       password_set = load_password(cur_pwd, &max_attempt, &expire_time);
+       /* If we cannot load password file */
+       if(password_set == SECURITY_SERVER_ERROR_SERVER_ERROR)
+       {
+               SEC_SVR_DBG("%s", "Server: Responding error because we cannot provide password service");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Receive size of pwds */
+       retval = read(sockfd, &cur_pwd_len, sizeof(char));
+       if(retval < sizeof(char) || cur_pwd_len > SECURITY_SERVER_MAX_PASSWORD_LEN)
+       {
+               SEC_SVR_DBG("Server Error: current password length recieve failed: %d, %d", retval, cur_pwd_len);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+       retval = read(sockfd, &new_pwd_len, sizeof(char));
+       if(retval < sizeof(char)  || new_pwd_len > SECURITY_SERVER_MAX_PASSWORD_LEN)
+       {
+               SEC_SVR_DBG("Server Error: new password length recieve failed: %d, %d", retval, new_pwd_len);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Receive current password */
+       if(cur_pwd_len > 0)
+       {
+               /* Check wheter current password is exist */
+               if(password_set == SECURITY_SERVER_SUCCESS)
+               retval = read(sockfd, requested_cur_pwd, cur_pwd_len);
+               if(retval < cur_pwd_len)
+               {
+                       SEC_SVR_DBG("Server Error: current password recieve failed: %d", retval);
+                       retval = send_generic_response(sockfd, 
+                                       SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE,
+                                       SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+                       if(retval != SECURITY_SERVER_SUCCESS)
+                       {
+                               SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+                       }
+                       goto error;
+               }
+               requested_cur_pwd[cur_pwd_len] = 0;
+       }
+       else /* Check first password set attempt but password is already set */
+       {
+               if(password_set == SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server Error: password is already set: %d", retval);
+                       retval = send_generic_response(sockfd, 
+                                       SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE,
+                                       SECURITY_SERVER_RETURN_CODE_PASSWORD_EXIST);
+                       if(retval != SECURITY_SERVER_SUCCESS)
+                       {
+                               SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+                       }
+                       goto error;
+               }
+       }
+
+       /* Receive new password */
+       retval = read(sockfd, requested_new_pwd, new_pwd_len);
+       if(retval < new_pwd_len)
+       {
+               SEC_SVR_DBG("Server Error:  new password recieve failed: %d", retval);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+       requested_new_pwd[new_pwd_len] = 0;
+
+       /* Receive max attempt */
+       retval = read(sockfd, &received_attempts, sizeof(unsigned int));
+       if(retval < sizeof(unsigned int))
+       {
+               SEC_SVR_DBG("Sever Error:  Max attempt receive failed: %d", retval);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Receive valid period  */
+       retval = read(sockfd, &valid_days, sizeof(unsigned int));
+       if(retval < sizeof(unsigned int))
+       {
+               SEC_SVR_DBG("Sever Error:  Max attempt receive failed: %d", retval);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Hash requested password */
+       SHA256_Init(&context);
+       SHA256_Update(&context, (unsigned char*)requested_cur_pwd, strlen(requested_cur_pwd));
+       SHA256_Final(hashed_challenge, &context);
+
+       SHA256_Init(&context);
+       SHA256_Update(&context, (unsigned char*)requested_new_pwd, strlen(requested_new_pwd));
+       SHA256_Final(hashed_new_pw, &context);
+       
+       /* check current password */
+       if(password_set  == SECURITY_SERVER_SUCCESS)
+       {
+               retval = check_password(cur_pwd, hashed_challenge, max_attempt, expire_time, &current_attempt);
+               if(retval == SECURITY_SERVER_ERROR_PASSWORD_MISMATCH)
+               {
+                       SEC_SVR_DBG("%s", "Server: Wrong password");
+                       retval = send_generic_response(sockfd, 
+                                       SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE,
+                                       SECURITY_SERVER_RETURN_CODE_PASSWORD_MISMATCH);
+                       if(retval != SECURITY_SERVER_SUCCESS)
+                       {
+                               SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+                       }
+                       goto error;
+               }
+               if(retval == SECURITY_SERVER_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED)
+               {
+                       SEC_SVR_DBG("%s", "Server: Too many challange");
+                       retval = send_generic_response(sockfd, 
+                                       SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE,
+                                       SECURITY_SERVER_RETURN_CODE_PASSWORD_MAX_ATTEMPTS_EXCEEDED);
+                       if(retval != SECURITY_SERVER_SUCCESS)
+                       {
+                               SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+                       }
+                       goto error;
+               }
+               if(retval == SECURITY_SERVER_ERROR_PASSWORD_EXPIRED)
+               {
+                       SEC_SVR_DBG("%s", "Server: Password expired");
+                       retval = send_generic_response(sockfd, 
+                                       SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE,
+                                       SECURITY_SERVER_RETURN_CODE_PASSWORD_EXPIRED);
+                       if(retval != SECURITY_SERVER_SUCCESS)
+                       {
+                               SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+                       }
+                       goto error;
+               }
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Error: Password check failed: %d", retval);
+                       retval = send_generic_response(sockfd, 
+                                       SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE,
+                                       SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
+                       if(retval != SECURITY_SERVER_SUCCESS)
+                       {
+                               SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+                       }
+                       goto error;
+               }
+               retval = check_history(hashed_new_pw);
+               if(retval == SECURITY_SERVER_ERROR_PASSWORD_REUSED)
+               {
+                       retval = send_generic_response(sockfd, 
+                                       SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE,
+                                       SECURITY_SERVER_RETURN_CODE_PASSWORD_REUSED);
+                       if(retval != SECURITY_SERVER_SUCCESS)
+                       {
+                               SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+                       }
+                       goto error;
+               }
+       }
+       else if(cur_pwd_len != 0)
+       {
+               /* Client ask to set with current password, but there is no password now */
+               SEC_SVR_DBG("%s", "Server: There is no current password. But try to set with current password");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_PASSWORD_MISMATCH);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Calculate expire time in seconds */
+       if(valid_days == 0)
+               expire_time = 0;
+       else
+               expire_time = time(NULL) + (valid_days * 86400);
+
+       /* set new password */
+       retval = set_password(hashed_new_pw, received_attempts, expire_time);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("Server Error: Password set failed: %d", retval);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               password_set = SECURITY_SERVER_ERROR_SERVER_ERROR;
+               goto error;
+       }
+       password_set = SECURITY_SERVER_SUCCESS;
+       retval = reset_attempt();
+
+       /* All done. send response */
+       SEC_SVR_DBG("%s", "Server: Password has been successfully modified");
+       retval = send_generic_response(sockfd, 
+                       SECURITY_SERVER_MSG_TYPE_SET_PWD_RESPONSE,
+                       SECURITY_SERVER_RETURN_CODE_SUCCESS);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+       }
+error:
+       return retval;
+}
+
+int process_reset_pwd_request(int sockfd)
+{
+       int retval, password_set;
+       char new_pwd_len;
+       unsigned int valid_days, received_attempts, expire_time;
+       char requested_new_pwd[SECURITY_SERVER_MAX_PASSWORD_LEN +1];
+       unsigned char hashed_new_pw[SECURITY_SERVER_HASHED_PWD_LEN];
+       unsigned char cur_pwd[SECURITY_SERVER_HASHED_PWD_LEN];
+       struct timeval cur_try;
+
+       SHA256_CTX context;
+
+       /* Authenticate client that peer is setting app goes here*/
+/*     
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("%s", "Client Authentication Failed");
+               retval = send_generic_response(client_sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_TOOL_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+*/
+
+       /* Check retry timer */
+       gettimeofday(&cur_try, NULL);
+       retval = check_retry(cur_try);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("%s", "Server: Retry timeout occurred");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_RESET_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_PASSWORD_RETRY_TIMER);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       password_set = load_password(cur_pwd, &valid_days, &expire_time);
+       if(password_set == SECURITY_SERVER_ERROR_SERVER_ERROR)
+       {
+               SEC_SVR_DBG("%s", "Server: Responding error because we cannot provide password service");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Receive size of pwd */
+       retval = read(sockfd, &new_pwd_len, sizeof(char));
+       if(retval < sizeof(char)  || new_pwd_len > SECURITY_SERVER_MAX_PASSWORD_LEN)
+       {
+               SEC_SVR_DBG("Server Error: new password length recieve failed: %d, %d", retval, new_pwd_len);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_RESET_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Receive new password */
+       retval = read(sockfd, requested_new_pwd, new_pwd_len);
+       if(retval < new_pwd_len)
+       {
+               SEC_SVR_DBG("Server Error:  new password recieve failed: %d", retval);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_RESET_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+       requested_new_pwd[new_pwd_len] = 0;
+
+       /* Receive max attempt */
+       retval = read(sockfd, &received_attempts, sizeof(unsigned int));
+       if(retval < sizeof(unsigned int))
+       {
+               SEC_SVR_DBG("Sever Error:  Max attempt receive failed: %d", retval);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_RESET_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Receive valid period  */
+       retval = read(sockfd, &valid_days, sizeof(unsigned int));
+       if(retval < sizeof(unsigned int))
+       {
+               SEC_SVR_DBG("Sever Error:  Max attempt receive failed: %d", retval);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_RESET_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Calculate expire time in seconds */
+       if(valid_days == 0)
+               expire_time = 0;
+       else
+               expire_time = time(NULL) + (valid_days * 86400);
+
+       /* Hash requested password */
+       SHA256_Init(&context);
+       SHA256_Update(&context, (unsigned char*)requested_new_pwd, strlen(requested_new_pwd));
+       SHA256_Final(hashed_new_pw, &context);
+       /* set new password */
+       retval = set_password(hashed_new_pw, received_attempts, expire_time);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("Server Error: Password set failed: %d", retval);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_RESET_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+       retval = reset_attempt();
+
+       /* All done. send response */
+       SEC_SVR_DBG("%s", "Server: Password has been successfully modified");
+       retval = send_generic_response(sockfd, 
+                       SECURITY_SERVER_MSG_TYPE_RESET_PWD_RESPONSE,
+                       SECURITY_SERVER_RETURN_CODE_SUCCESS);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+       }
+error:
+       return retval;
+}
+
+int process_chk_pwd_request(int sockfd)
+{
+       int retval, password_set, current_attempt;
+       unsigned int max_attempt, expire_time;
+       char requested_challenge[SECURITY_SERVER_MAX_PASSWORD_LEN+1];
+       char challenge_len;
+       unsigned char cur_pwd[SECURITY_SERVER_HASHED_PWD_LEN];
+       unsigned char hashed_challenge[SECURITY_SERVER_HASHED_PWD_LEN];
+       struct timeval cur_try;
+
+       SHA256_CTX context;
+
+       /* Authenticate client that peer is proper app goes here*/
+       /* Check SMACK rule for the 'r' for password */
+       retval = SECURITY_SERVER_SUCCESS;
+/*
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("%s", "Client Authentication Failed");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_TOOL_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+*/
+       /* Check retry timer */
+       gettimeofday(&cur_try, NULL);
+       retval = check_retry(cur_try);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("%s", "Server: Retry timeout occurred");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_CHK_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_PASSWORD_RETRY_TIMER);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* If we cannot load password file */
+       password_set = load_password(cur_pwd, &max_attempt, &expire_time);;
+       if(password_set == SECURITY_SERVER_ERROR_SERVER_ERROR)
+       {
+               SEC_SVR_DBG("%s", "ServerERROR: Responding error because we cannot provide password service");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_CHK_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Receive size of challenge */
+       retval = read(sockfd, &challenge_len, sizeof(char));
+       if(retval < sizeof(char) || challenge_len > SECURITY_SERVER_MAX_PASSWORD_LEN)
+       {
+               SEC_SVR_DBG("Server ERROR: challenge length recieve failed: %d", retval);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_CHK_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+       /* Receive challenge */
+       if(challenge_len > 0)
+       {
+               retval = read(sockfd, requested_challenge, challenge_len);
+               if(retval < challenge_len)
+               {
+                       SEC_SVR_DBG("Server ERROR: current password recieve failed: %d", retval);
+                       retval = send_generic_response(sockfd, 
+                                       SECURITY_SERVER_MSG_TYPE_CHK_PWD_RESPONSE,
+                                       SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+                       if(retval != SECURITY_SERVER_SUCCESS)
+                       {
+                               SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+                       }
+                       goto error;
+               }
+               requested_challenge[challenge_len] = 0;
+       }
+       else
+       {
+               SEC_SVR_DBG("Error: Challenge length too short: %d", retval);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_CHK_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Hash requested password */
+       SHA256_Init(&context);
+       SHA256_Update(&context, (unsigned char*)requested_challenge, challenge_len);
+       SHA256_Final(hashed_challenge, &context);
+
+       /* check current password */
+       if(password_set  == SECURITY_SERVER_SUCCESS)
+       {
+               retval = check_password(cur_pwd, hashed_challenge, max_attempt, expire_time, &current_attempt);
+               if(retval == SECURITY_SERVER_ERROR_PASSWORD_MISMATCH)
+               {
+                       SEC_SVR_DBG("%s", "Server: Wrong password");
+                       retval = send_pwd_response(sockfd, 
+                                       SECURITY_SERVER_MSG_TYPE_CHK_PWD_RESPONSE,
+                                       SECURITY_SERVER_RETURN_CODE_PASSWORD_MISMATCH, 
+                                       current_attempt, max_attempt, expire_time);
+                       if(retval != SECURITY_SERVER_SUCCESS)
+                       {
+                               SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+                       }
+                       goto error;
+               }
+               if(retval == SECURITY_SERVER_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED)
+               {
+                       SEC_SVR_DBG("%s", "Server: Too many trial");
+                       retval = send_pwd_response(sockfd, 
+                                       SECURITY_SERVER_MSG_TYPE_CHK_PWD_RESPONSE,
+                                       SECURITY_SERVER_RETURN_CODE_PASSWORD_MAX_ATTEMPTS_EXCEEDED,
+                                       current_attempt, max_attempt, expire_time);
+                       if(retval != SECURITY_SERVER_SUCCESS)
+                       {
+                               SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+                       }
+                       goto error;
+               }
+               if(retval == SECURITY_SERVER_ERROR_PASSWORD_EXPIRED)
+               {
+                       SEC_SVR_DBG("%s", "Server: Password expired");
+                       retval = send_pwd_response(sockfd, 
+                                       SECURITY_SERVER_MSG_TYPE_CHK_PWD_RESPONSE,
+                                       SECURITY_SERVER_RETURN_CODE_PASSWORD_EXPIRED,
+                                       current_attempt, max_attempt, 0);
+                       if(retval != SECURITY_SERVER_SUCCESS)
+                       {
+                               SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+                       }
+                       goto error;
+               }
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Password check failed: %d", retval);
+                       retval = send_generic_response(sockfd, 
+                                       SECURITY_SERVER_MSG_TYPE_CHK_PWD_RESPONSE,
+                                       SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
+                       if(retval != SECURITY_SERVER_SUCCESS)
+                       {
+                               SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+                       }
+                       goto error;
+               }
+
+               /* Password matched */
+               SEC_SVR_DBG("%s", "Server: Password matched");
+               retval = send_pwd_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_CHK_PWD_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_SUCCESS,
+                               current_attempt, max_attempt, expire_time);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               retval = reset_attempt();
+               goto error;
+       }
+
+       /* There is no password */
+       
+       SEC_SVR_DBG("%s", "Server: There is no password to be checked");
+       retval = send_generic_response(sockfd, 
+                       SECURITY_SERVER_MSG_TYPE_CHK_PWD_RESPONSE,
+                       SECURITY_SERVER_RETURN_CODE_NO_PASSWORD);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+       }
+error:
+       return retval;
+}
+
+int process_set_pwd_history_request(int sockfd)
+{
+       int retval;
+       char history_num;
+       struct timeval cur_try;
+
+       /* Authenticate client that peer is setting app goes here*/
+/*
+       f(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("%s", "Client Authentication Failed");
+               retval = send_generic_response(client_sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_TOOL_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+*/
+
+       /* Check retry timer */
+       gettimeofday(&cur_try, NULL);
+       retval = check_retry(cur_try);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("%s", "Server: Retry timeout occurred");
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_SET_PWD_HISTORY_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_PASSWORD_RETRY_TIMER);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       /* Receive size of pwds */
+       retval = read(sockfd, &history_num, sizeof(char));
+       if(retval < sizeof(char) || history_num > SECURITY_SERVER_MAX_PASSWORD_HISTORY || history_num < 0 )
+       {
+               SEC_SVR_DBG("Server Error: History number recieve failed: %d, %d", retval, history_num);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_SET_PWD_HISTORY_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+               goto error;
+       }
+
+       retval = set_history((int)history_num);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("Server Error: History number set failed: %d", retval);
+               retval = send_generic_response(sockfd, 
+                               SECURITY_SERVER_MSG_TYPE_SET_PWD_HISTORY_RESPONSE,
+                               SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
+               if(retval != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+               }
+       }
+       SEC_SVR_DBG("Server History has been set to %d", history_num);
+       retval = send_generic_response(sockfd, 
+                       SECURITY_SERVER_MSG_TYPE_SET_PWD_HISTORY_RESPONSE,
+                       SECURITY_SERVER_RETURN_CODE_SUCCESS);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               SEC_SVR_DBG("Server ERROR: Cannot send generic response: %d", retval);
+       }
+error:
+       return retval;
+}
diff --git a/src/util/security-server-util-common.c b/src/util/security-server-util-common.c
new file mode 100644 (file)
index 0000000..6db71c1
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "security-server-common.h"
+#include "security-server-cookie.h"
+#include "security-server-comm.h"
+#include "security-server-util.h"
+#include "security-server.h"
+
+
+/* Get all cookie info response *
+ * packet format
+ *  0                   1                   2                   3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x52 |       Message Length          |
+ * |---------------------------------------------------------------|
+ * |  return code  |             tot # of cooks (32bit)            |
+ * |---------------------------------------------------------------|
+ * |   cont'd...   |            1st cmdline_len (32bit)            |
+ * |---------------------------------------------------------------|
+ * |   cont'd...   |           1st permission_len (32bit)          |
+ * ----------------------------------------------------------------|
+ * |   cont'd...   |                                               |
+ * |----------------                                               |
+ * |                         1st cookie                            |
+ * |                                                               |
+ * |---------------------------------------------------------------|
+ * |                         1st PID (32bit)                       |
+ * |---------------------------------------------------------------|
+ * |                     1st cmdline (string)                      |
+ * |---------------------------------------------------------------|
+ * |                           1st perm_1                          |
+ * |---------------------------------------------------------------|
+ * |                           1st perm_2                          |
+ * |---------------------------------------------------------------|
+ * |                              ...                              |
+ * |---------------------------------------------------------------|
+ * |                      2nd cmdline_len  (32bit)                 |
+ * |---------------------------------------------------------------|
+ * |                     2nd permission_len (32bit)                |
+ * |---------------------------------------------------------------|
+ * |                                                               |
+ * |                        2nd cookie                             |
+ * |                                                               |
+ * |---------------------------------------------------------------|
+ * |                         2nd PID (32 bit)                      |
+ * |---------------------------------------------------------------|
+ * |                     2nd cmdline (string)                      |
+ * |---------------------------------------------------------------|
+ * |                           2st perm_1                          |
+ * |---------------------------------------------------------------|
+ * |                           2st perm_2                          |
+ * |---------------------------------------------------------------|
+ * |                              ...                              |
+ * |---------------------------------------------------------------|
+ * |                                                               |
+ * |                             ...                               |
+ * |                                                               |
+ * |                                                               |
+ */
+ unsigned char * get_all_cookie_info(cookie_list *list, int *size)
+{
+       cookie_list *current = list;
+       int ptr, total_num, total_size, tempnum, i;
+       unsigned char *buf = NULL, *tempptr = NULL;
+       response_header hdr;
+
+       total_size = sizeof(hdr) + sizeof(int);
+
+       buf = malloc(total_size); /* header size */
+       ptr = sizeof(hdr) + sizeof(int);
+       total_num = 0;  /* Total # of cookies initial value */
+
+       while(current != NULL)
+       {
+               current = garbage_collection(current);
+               if(current == NULL)
+                       break;
+
+               total_num++;
+               total_size += sizeof(int) + sizeof(int) + SECURITY_SERVER_COOKIE_LEN + sizeof(int) + current->path_len + (current->permission_len * sizeof(int));
+               tempptr = realloc(buf, total_size);
+               if(tempptr == NULL)
+               {
+                       SEC_SVR_DBG("%s", "Out of memory");
+                       return NULL;
+               }
+               buf = tempptr;
+
+               tempnum = current->path_len;
+               memcpy(buf+ptr, &tempnum, sizeof(int));
+               ptr += sizeof(int);
+               tempnum = current->permission_len;
+               memcpy(buf+ptr, &tempnum, sizeof(int));
+               ptr += sizeof(int);
+               memcpy(buf+ptr, current->cookie, SECURITY_SERVER_COOKIE_LEN);
+               ptr += SECURITY_SERVER_COOKIE_LEN;
+               tempnum = current->pid;
+               memcpy(buf+ptr, &tempnum, sizeof(int));
+               ptr += sizeof(int);
+               memcpy(buf+ptr, current->path, current->path_len);
+               ptr += current->path_len;
+
+               for(i=0;i<current->permission_len;i++)
+               {
+                       tempnum = current->permissions[i];
+                       memcpy(buf+ptr, &tempnum, sizeof(int));
+                       ptr += sizeof(int);
+               }
+               current = current->next;
+       }
+
+       if(total_size > 65530)
+       {
+               SEC_SVR_DBG("Packet too big. message length overflow: %d", total_size);
+               free(buf);
+               return  NULL;
+       }
+
+       hdr.basic_hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.basic_hdr.msg_id = SECURITY_SERVER_MSG_TYPE_GET_ALL_COOKIES_RESPONSE;
+       hdr.basic_hdr.msg_len =(unsigned short)( total_size - sizeof(hdr));
+       hdr.return_code = SECURITY_SERVER_RETURN_CODE_SUCCESS;
+       memcpy(buf, &hdr, sizeof(hdr));
+       tempnum = total_num;
+       memcpy(buf + sizeof(hdr), &tempnum, sizeof(int));
+       *size = total_size;
+       return buf;
+}
+
+int send_all_cookie_info(const unsigned char *buf, int size, int sockfd)
+{
+       int ret;
+       /* Check poll */
+       ret = check_socket_poll(sockfd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(ret == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       if(ret == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+
+       /* Send to client */
+       ret = write(sockfd, buf, size);
+
+       if(ret < size)
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       return SECURITY_SERVER_SUCCESS;
+}
+
+/* Get one cookie info response *
+ * packet format
+ *  0                   1                   2                   3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x54 |       Message Length          |
+ * |---------------------------------------------------------------|
+ * |  return code  |              cmdline_len (32bit)t)            |
+ * |---------------------------------------------------------------|
+ * |   cont'd...   |              permission_len (32bit)           |
+ * ----------------------------------------------------------------|
+ * |   cont'd...   |                                               |
+ * |----------------                                               |
+ * |                             cookie                            |
+ * |                                                               |
+ * |---------------------------------------------------------------|
+ * |                           PID (32bit)                         |
+ * |---------------------------------------------------------------|
+ * |                         cmdline (string)                      |
+ * |---------------------------------------------------------------|
+ * |                             perm_1                            |
+ * |---------------------------------------------------------------|
+ * |                             perm_2                            |
+ * |---------------------------------------------------------------|
+ * |                              ...                              |
+ * |---------------------------------------------------------------|
+*/
+int send_one_cookie_info(const cookie_list *list, int sockfd)
+{
+       unsigned char *buf = NULL;
+       response_header hdr;
+       int total_size, ptr = 0, tempnum, ret, i;
+
+       total_size = sizeof(hdr) + sizeof(int) + sizeof(int) + SECURITY_SERVER_COOKIE_LEN + sizeof(int) + list->path_len + (list->permission_len * sizeof(int));
+       buf = malloc(total_size);
+       if(buf == NULL)
+       {
+               SEC_SVR_DBG("%s", "Out of memory");
+               return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+       }
+
+       hdr.basic_hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.basic_hdr.msg_id = SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_RESPONSE;
+       hdr.basic_hdr.msg_len =sizeof(int) + sizeof(int) + SECURITY_SERVER_COOKIE_LEN + sizeof(int) + list->path_len + (list->permission_len * sizeof(int));
+       hdr.return_code = SECURITY_SERVER_RETURN_CODE_SUCCESS;
+       memcpy(buf, &hdr, sizeof(hdr));
+       ptr += sizeof(hdr);
+
+       tempnum = list->path_len;
+       memcpy(buf+ptr, &tempnum, sizeof(int));
+       ptr += sizeof(int);
+       tempnum = list->permission_len;
+       memcpy(buf+ptr, &tempnum, sizeof(int));
+       ptr += sizeof(int);
+       memcpy(buf+ptr, list->cookie, SECURITY_SERVER_COOKIE_LEN);
+       ptr += SECURITY_SERVER_COOKIE_LEN;
+       tempnum = list->pid;
+       memcpy(buf+ptr, &tempnum, sizeof(int));
+       ptr += sizeof(int);
+       memcpy(buf+ptr, list->path, list->path_len);
+       ptr += list->path_len;
+
+       for(i=0;i<list->permission_len;i++)
+       {
+               tempnum = list->permissions[i];
+               memcpy(buf+ptr, &tempnum, sizeof(int));
+               ptr += sizeof(int);
+       }
+
+       ret = check_socket_poll(sockfd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(ret == SECURITY_SERVER_ERROR_POLL)
+       {
+               SEC_SVR_DBG("%s", "poll() error");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       if(ret == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               SEC_SVR_DBG("%s", "poll() timeout");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+
+       /* Send to client */
+       ret = write(sockfd, buf, total_size);
+
+       if(ret < total_size)
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       return SECURITY_SERVER_SUCCESS;
+}
+
+int util_process_all_cookie(int sockfd, cookie_list* list)
+{
+       unsigned char *buf = NULL;
+       int ret;
+       buf = get_all_cookie_info(list, &ret);
+       if(buf == NULL)
+       {
+               return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+       }
+
+       ret = send_all_cookie_info(buf, ret, sockfd);
+
+       if(buf != NULL)
+               free(buf);
+       return ret;
+}
+int util_process_cookie_from_pid(int sockfd, cookie_list* list)
+{
+       int pid, ret;
+       cookie_list *result = NULL;
+
+       ret = read(sockfd, &pid, sizeof(int));
+       if(ret < sizeof(int))
+       {
+               SEC_SVR_DBG("Received cookie size is too small: %d", ret);
+               return SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+       if(pid == 0)
+       {
+               SEC_SVR_DBG("%s", "ERROR: Default cookie is not allowed to be retrieved");
+               ret = send_generic_response(sockfd, SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_RESPONSE,
+                       SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+               if(ret != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", ret);
+               }
+       }
+       result = search_cookie_from_pid(list, pid);
+       if(result == NULL)
+       {
+               ret = send_generic_response(sockfd, SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_RESPONSE,
+                       SECURITY_SERVER_RETURN_CODE_NO_SUCH_COOKIE);
+               if(ret != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", ret);
+               }
+       }
+       else
+       {
+               ret = send_one_cookie_info(result, sockfd);
+               if(ret != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send cookie info response: %d", ret);
+               }
+       }
+       
+       return ret;
+}
+
+int util_process_cookie_from_cookie(int sockfd, cookie_list* list)
+{
+       unsigned char cookie[SECURITY_SERVER_COOKIE_LEN];
+       int ret;
+       cookie_list *result = NULL;
+
+       ret = read(sockfd, cookie, SECURITY_SERVER_COOKIE_LEN);
+       if(ret < SECURITY_SERVER_COOKIE_LEN)
+       {
+               SEC_SVR_DBG("Received cookie size is too small: %d", ret);
+               return SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+       result = search_cookie(list, cookie, 0);
+       if(result == NULL)
+       {
+               ret = send_generic_response(sockfd, SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_RESPONSE,
+                       SECURITY_SERVER_RETURN_CODE_NO_SUCH_COOKIE);
+               if(ret != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", ret);
+               }
+       }
+       else
+       {
+               ret = send_one_cookie_info(result, sockfd);
+               if(ret != SECURITY_SERVER_SUCCESS)
+               {
+                       SEC_SVR_DBG("ERROR: Cannot send cookie info response: %d", ret);
+               }
+       }
+       
+       return ret;
+}
diff --git a/src/util/security-server-util.c b/src/util/security-server-util.c
new file mode 100644 (file)
index 0000000..3cc1aff
--- /dev/null
@@ -0,0 +1,773 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "security-server.h"
+#include "security-server-common.h"
+#include "security-server-util.h"
+#include "security-server-comm.h"
+
+#define TOTAL_PATH_MAX 256
+
+#define mszBase64Table  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
+#define BASE64_PAD      '='
+
+
+
+ void printusage(char *cmdline)
+{
+       printf("%s\n", "Usage: ");
+       printf("%s [Options]\n", cmdline);
+       printf("%s\n", "[Options]");
+       printf("%s\n", "-a:\tList all active cookies ");
+       printf("%s\n", "-f [filename]:\tList a specific cookie information from file");
+       printf("%s\n", "\tThe file must contain binary form of cookie");
+       printf("%s\n", "-p [pid]:\tList a specific cookie information for a process by PID");
+       printf("%s\n", "-s [base64 encoded cookie]:\tList a specific cookie information for a process by given base64 encoded cookie value");
+       printf("%s\n", "Example:");
+       printf("%s -a\n", cmdline);
+       printf("%s -f /tmp/mycookie.bin\n", cmdline);
+       printf("%s -p 2115\n", cmdline);
+       printf("%s -s asC34fddaxd6NDVDA43GFD345TfCADF==\n", cmdline);
+}
+
+void printstr(const unsigned char *data, int size)
+{
+       int i;
+       for(i=0;i<size;i++)
+       {
+               printf("%c", data[i]);
+       }
+       printf("\n");
+}
+
+void printperm(const unsigned char *data, int num)
+{
+       int i, ptr, tempnum;
+       for(i=0, ptr=0;i<num;i++)
+       {
+               memcpy(&tempnum, data+ptr, sizeof(int));
+               printf("%d, ", tempnum);
+               ptr+= sizeof(int);
+               if(i % 6 == 0 && i != 0)
+                       printf("\n");
+       }
+       printf("\n");
+}
+
+/* Send all cookie information request packet to security server *
+ * 
+ * Message format
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x51 |       Message Length = 0      |
+ * |---------------------------------------------------------------|
+ */
+int send_all_cookie_info_request(int sockfd)
+{
+
+       basic_header hdr;
+       int retval;
+
+       /* Assemble header */
+       hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.msg_id = SECURITY_SERVER_MSG_TYPE_GET_ALL_COOKIES_REQUEST;
+       hdr.msg_len = 0;
+
+       /* Check poll */
+       retval = check_socket_poll(sockfd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               printf("Error: %s\n", "poll() error");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               printf("Error: %s\n", "poll() timeout");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+
+       /* Send to server */
+       retval = write(sockfd, &hdr, sizeof(hdr));
+       if(retval < sizeof(hdr))
+       {
+               /* Write error */
+               printf("Error on write(): %d\n", retval);
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       return SECURITY_SERVER_SUCCESS; 
+}
+
+int recv_all_cookie_info(int sockfd)
+{
+       int retval, total_cookie, ptr = 0, i, cmdline_len, perm_len, recved_pid;
+       response_header hdr;
+       unsigned char *buf = NULL;
+
+       /* Check poll */
+       retval = check_socket_poll(sockfd, POLLIN, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               printf("Error: %s\n", "poll() error");
+               return SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               printf("Error: %s\n", "poll() timeout");
+               return SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+
+       /* Receive response */
+       retval = read(sockfd, &hdr, sizeof(response_header));
+       if(retval < sizeof(hdr) )
+       {
+               /* Error on socket */
+               printf("Error: Receive failed %d\n", retval);
+               return  SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+
+       if(hdr.return_code != SECURITY_SERVER_RETURN_CODE_SUCCESS)
+       {
+               printf("Error: response error: %d\n", hdr.return_code);
+               return return_code_to_error_code(hdr.return_code);
+       }
+
+       if(hdr.basic_hdr.msg_id != SECURITY_SERVER_MSG_TYPE_GET_ALL_COOKIES_RESPONSE)
+       {
+               printf("Error: response error: different msg type %d\n", hdr.basic_hdr.msg_id );
+               return SECURITY_SERVER_ERROR_BAD_RESPONSE;
+       }
+
+       buf = malloc(hdr.basic_hdr.msg_len);
+       if(buf == NULL)
+       {
+               printf("Error: Out of memory\n");
+               return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+       }
+
+       retval = read(sockfd, buf, hdr.basic_hdr.msg_len);
+       if(retval < hdr.basic_hdr.msg_len)
+       {
+               printf("Error: receiving too small amount. %d, %d\n", retval,  hdr.basic_hdr.msg_len);
+               printhex(buf, retval);
+               if(buf != NULL)
+                       free(buf);
+               return SECURITY_SERVER_ERROR_BAD_RESPONSE;
+       }
+
+       memcpy(&total_cookie, buf, sizeof(int));
+       if(total_cookie == 0)
+       {
+               printf("There is no cookie available\n");
+               if(buf != NULL)
+                       free(buf);
+               return SECURITY_SERVER_SUCCESS;
+       }
+       ptr = sizeof(int);
+       printf("--------------------------------\n");
+       for(i=0;i<total_cookie;i++)
+       {
+               printf("%dth cookie:\n", i+1);
+               memcpy(&cmdline_len, buf+ptr, sizeof(int));
+               ptr += sizeof(int);
+               memcpy(&perm_len, buf+ptr, sizeof(int));
+               ptr+= sizeof(int);
+
+               printf("%s\n", "Cookie:");
+               printhex(buf + ptr, SECURITY_SERVER_COOKIE_LEN);
+               ptr += SECURITY_SERVER_COOKIE_LEN;
+               memcpy(&recved_pid, buf+ptr, sizeof(int));
+               ptr+= sizeof(int);
+               if(recved_pid == 0)
+               {
+                       printf("PID: %d (default cookie - for all root processes)\n", recved_pid);
+                       printf("%s\n", "cmdline: N/A");
+                       printf("%s\n", "Permissions (gids): N/A");
+               }
+               else
+               {
+                       printf("PID: %d\n", recved_pid);
+
+                       printf("%s\n", "cmdline:");
+                       printstr(buf + ptr, cmdline_len);
+                       ptr += cmdline_len;
+
+                       printf("%s\n", "Permissions (gids):");
+                       printperm(buf + ptr, perm_len);
+                       ptr += (perm_len * sizeof(int));
+               }
+               printf("--------------------------------\n");
+       }
+       if(buf != NULL)
+               free(buf);
+       return SECURITY_SERVER_SUCCESS;
+}
+
+/* Send cookie information request from cookie packet to security server *
+ * 
+ * Message format
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x55 |       Message Length = 20     |
+ * |---------------------------------------------------------------|
+ * |                                                               |
+ * |                         cookie                                |
+ * |                                                               |
+ * |---------------------------------------------------------------|
+ */
+int send_cookie_info_request_from_cookie(int sockfd, const unsigned char *cookie)
+{
+
+       basic_header hdr;
+       int retval;
+       int size = sizeof(hdr) + SECURITY_SERVER_COOKIE_LEN;
+       unsigned char buf[size];
+
+       /* Assemble header */
+       hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.msg_id = SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_FROM_COOKIE_REQUEST;
+       hdr.msg_len = SECURITY_SERVER_COOKIE_LEN;
+
+       memcpy(buf, &hdr, sizeof(hdr));
+       memcpy(buf + sizeof(hdr), cookie, SECURITY_SERVER_COOKIE_LEN);
+
+       /* Check poll */
+       retval = check_socket_poll(sockfd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               printf("Error: %s\n", "poll() error");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               printf("Error: %s\n", "poll() timeout");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+
+       /* Send to server */
+       retval = write(sockfd, buf, size);
+       if(retval < size)
+       {
+               /* Write error */
+               printf("Error on write(): %d\n", retval);
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       return SECURITY_SERVER_SUCCESS; 
+}
+
+/* Send cookie information request from pid packet to security server *
+ * 
+ * Message format
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * |---------------------------------------------------------------|
+ * | version=0x01  |MessageID=0x53 |       Message Length = 20     |
+ * |---------------------------------------------------------------|
+ * |                            pid                                |
+ * |---------------------------------------------------------------|
+ */
+int send_cookie_info_request_from_pid(int sockfd, int pid)
+{
+       basic_header hdr;
+       int retval;
+       int size = sizeof(hdr) + sizeof(int);
+       unsigned char buf[size];
+
+       /* Assemble header */
+       hdr.version = SECURITY_SERVER_MSG_VERSION;
+       hdr.msg_id = SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_FROM_PID_REQUEST;
+       hdr.msg_len = SECURITY_SERVER_COOKIE_LEN;
+       memcpy(buf, &hdr, sizeof(hdr));
+       memcpy(buf+sizeof(hdr), &pid, sizeof(int));
+
+       /* Check poll */
+       retval = check_socket_poll(sockfd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               printf("Error: %s\n", "poll() error");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               printf("Error: %s\n", "poll() timeout");
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+
+       /* Send to server */
+       retval = write(sockfd, buf, size);
+       if(retval < size)
+       {
+               /* Write error */
+               printf("Error on write(): %d\n", retval);
+               return SECURITY_SERVER_ERROR_SEND_FAILED;
+       }
+       return SECURITY_SERVER_SUCCESS; 
+}
+
+int recv_cookie_info_response(sockfd)
+{
+       unsigned char *buf = NULL;
+       int retval, cmdline_len, perm_len, recved_pid, ptr = 0;
+       response_header hdr;
+
+       /* Check poll */
+       retval = check_socket_poll(sockfd, POLLIN, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+       if(retval == SECURITY_SERVER_ERROR_POLL)
+       {
+               printf("Error: %s\n", "poll() error");
+               return SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+       if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+       {
+               printf("Error: %s\n", "poll() timeout");
+               return SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+
+       /* Receive response */
+       retval = read(sockfd, &hdr, sizeof(response_header));
+       if(retval < sizeof(hdr) )
+       {
+               /* Error on socket */
+               printf("Error: Receive failed %d\n", retval);
+               return  SECURITY_SERVER_ERROR_RECV_FAILED;
+       }
+
+       if(hdr.return_code != SECURITY_SERVER_RETURN_CODE_SUCCESS)
+       {
+               printf("Error: response error: %d\n", hdr.return_code);
+               return return_code_to_error_code(hdr.return_code);
+       }
+
+       if(hdr.basic_hdr.msg_id != SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_RESPONSE)
+       {
+               printf("Error: response error: different msg type %d\n" ,hdr.basic_hdr.msg_id);
+               return SECURITY_SERVER_ERROR_BAD_RESPONSE;
+       }
+
+       buf = malloc(hdr.basic_hdr.msg_len);
+       if(buf == NULL)
+       {
+               printf("Error: Out of memory\n");
+               return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+       }
+
+       retval = read(sockfd, buf, hdr.basic_hdr.msg_len);
+       if(retval < hdr.basic_hdr.msg_len)
+       {
+               printf("Error: receiving too small amount. %d, %d\n", retval,  hdr.basic_hdr.msg_len);
+               printhex(buf, retval);
+               if(buf != NULL)
+                       free(buf);
+               return SECURITY_SERVER_ERROR_BAD_RESPONSE;
+       }
+
+       memcpy(&cmdline_len, buf+ptr, sizeof(int));
+       ptr += sizeof(int);
+       memcpy(&perm_len, buf+ptr, sizeof(int));
+       ptr+= sizeof(int);
+
+       printf("%s\n", "Cookie:");
+       printhex(buf + ptr, SECURITY_SERVER_COOKIE_LEN);
+       ptr += SECURITY_SERVER_COOKIE_LEN;
+       memcpy(&recved_pid, buf+ptr, sizeof(int));
+       ptr+= sizeof(int);
+       if(recved_pid == 0)
+       {
+               printf("PID: %d (default cookie - for all root processes)\n", recved_pid);
+               printf("%s\n", "cmdline: N/A");
+               printf("%s\n", "Permissions (gids): N/A");
+       }
+       else
+       {
+               printf("PID: %d\n", recved_pid);
+
+               printf("%s\n", "cmdline:");
+               printstr(buf + ptr, cmdline_len);
+               ptr += cmdline_len;
+
+               printf("%s\n", "Permissions (gids):");
+               printperm(buf + ptr, perm_len);
+       }
+
+       free(buf);
+
+       return SECURITY_SERVER_SUCCESS;
+}
+
+void util_send_all_cookie_info_request(void)
+{
+       int sockfd = -1, retval;
+
+       retval = connect_to_server(&sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               printf("Error: %s\n", "connection failed");
+               goto error;
+       }
+
+       /* make request packet */
+       retval = send_all_cookie_info_request(sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Error: send request failed: %d", retval);
+               goto error;
+       }
+       retval = recv_all_cookie_info(sockfd);
+       if(retval <0)
+       {
+               printf("Error: Error receiving cookie list: %d\n", retval);
+               goto error;
+       }
+
+error:
+       if(sockfd > 0)
+       {
+               close(sockfd);
+       }
+       return;
+}
+
+void util_read_cookie_from_bin_file(unsigned char *cookie, const char *path)
+{
+       char total_path[TOTAL_PATH_MAX] = {0, };
+       FILE *fp = NULL;
+       int ret;
+
+       if(path[0] == '/' || (path[0] == '.' && path[1] == '/'))
+       {
+               /* Using absolute path */
+               strncpy(total_path, path, TOTAL_PATH_MAX);
+       }
+       else
+       {
+               if (getcwd(total_path, TOTAL_PATH_MAX) == NULL)
+               {
+                       printf("Cannot open cookie file\n");
+                       exit(1);
+               }
+               snprintf(total_path, TOTAL_PATH_MAX, "%s/%s", total_path, path);
+       }
+
+       fp = fopen(total_path, "rb");
+       if(fp == NULL)
+       {
+               printf("Cannot open cookie file\n");
+               exit(1);
+       }
+
+       ret = fread(cookie, 1, SECURITY_SERVER_COOKIE_LEN, fp);
+       if(ret < SECURITY_SERVER_COOKIE_LEN)
+       {
+               printf("Cannot read cookie file: %d\n", ret);
+               fclose(fp);
+               exit(1);
+       }
+
+       fclose(fp);
+       return;
+}
+
+void util_send_cookie_info_request_from_cookie(unsigned char *cookie)
+{
+       int sockfd = -1, retval;
+
+       retval = connect_to_server(&sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               printf("Error: %s\n", "connection failed");
+               goto error;
+       }
+
+       /* make request packet */
+       retval = send_cookie_info_request_from_cookie(sockfd, cookie);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Error: send request failed: %d", retval);
+               goto error;
+       }
+       retval = recv_cookie_info_response(sockfd);
+       if(retval == SECURITY_SERVER_ERROR_NO_SUCH_COOKIE)
+       {
+               printf("There is no such cookie available\n");
+               goto error;
+       }
+       if(retval <0)
+       {
+               printf("Error: Error receiving cookie info: %d\n", retval);
+               goto error;
+       }
+
+error:
+       if(sockfd > 0)
+       {
+               close(sockfd);
+       }
+       return;
+}
+
+unsigned char* util_base64_decode(unsigned char* input, long inputLength, long* outputLength)
+{
+       unsigned char* pCurIn = input;
+       unsigned char* pCurOut;
+       long iOutCharNum = 0;
+       long lInputLength = inputLength;
+       char buf[4];
+       unsigned char* inCode;
+       unsigned char* output;
+       (*outputLength) = 0;
+       if((input == NULL) || (inputLength <= 0))
+       return NULL;
+
+        /* calculate length of output data */
+       for(; lInputLength > 0; lInputLength--)
+       {
+               if ((*pCurIn) == BASE64_PAD)
+               {
+                       (*outputLength) += ((iOutCharNum + 1) >> 1);
+                       if ((iOutCharNum == 2) &&
+                       ((lInputLength == 1) ||
+                       (*(pCurIn + 1) != BASE64_PAD)))
+                       {
+                               (*outputLength)++;
+                       }
+                       iOutCharNum = 0;
+                       break;
+               }
+               inCode = (unsigned char*)strchr(mszBase64Table, *(pCurIn++));
+               if (!inCode)
+                       continue;
+               iOutCharNum++;
+               if (iOutCharNum == 4)
+               {
+                       (*outputLength) += 3;
+                       iOutCharNum=0;
+               }
+       }
+       (*outputLength) += ((iOutCharNum + 1)/2);
+
+       /* allocate memory for output data*/
+       output = malloc( *outputLength + 1 );
+       if(NULL == output)
+       {
+               return NULL;
+       }
+       memset( output, 0, (*outputLength + 1) );
+       pCurOut = output;
+       iOutCharNum = buf[0] = buf[1] = buf[2] = buf[3] = 0;
+
+       /* decode data*/
+       pCurIn = input;
+
+       for(; inputLength>0; inputLength--)
+       {
+               if ((*pCurIn) == BASE64_PAD)
+               {
+                       /*end-padding processing*/
+                       if (iOutCharNum == 0)
+                       {
+                               return output;
+                       }
+                       (*(pCurOut++)) = ((buf[0] & 0x3F) << 2) + ((buf[1] & 0x30) >> 4);
+                       if ((iOutCharNum == 3)||((iOutCharNum == 2) && ((lInputLength == 0) ||
+                       ((*(pCurIn + 1)) != BASE64_PAD))))
+                       {
+                               (*(pCurOut++)) = ((buf[1] & 0x0F) << 4) + ((buf[2] & 0x3C) >> 2);
+                       }
+                       return output;
+               }
+               inCode = (unsigned char*)strchr(mszBase64Table, *(pCurIn++));
+               if (!inCode)
+               {
+                       continue;
+               }
+               buf[iOutCharNum++] = (char)((unsigned long)inCode - (unsigned long)mszBase64Table);
+               if (iOutCharNum == 4)
+               {
+                       *(pCurOut++) = ((buf[0] & 0x3F) << 2) + ((buf[1] & 0x30) >> 4);
+                       *(pCurOut++) = ((buf[1] & 0x0F) << 4) + ((buf[2] & 0x3C) >> 2);
+                       *(pCurOut++) = ((buf[2] & 0x03) << 6) + (buf[3] & 0x3F);
+                       iOutCharNum = buf[0] = buf[1] = buf[2] = buf[3] = 0;
+               }
+       }
+       if (iOutCharNum == 0)
+       {
+               return output;
+       }
+       (*(pCurOut++)) = ((buf[0] & 0x3F) << 2) + ((buf[1] & 0x30) >> 4);
+       if (iOutCharNum == 3)
+       {
+               (*(pCurOut++)) = ((buf[1] & 0x0F) << 4) + ((buf[2] & 0x3C) >> 2);
+       }
+       return output;
+}
+
+void util_read_cookie_from_base64_string(unsigned char *cookie, const char *encoded_cookie)
+{
+       unsigned char *decoded_cookie = NULL;
+       int encoded_len, decoded_len;
+       encoded_len = strlen(encoded_cookie);
+
+       decoded_cookie = util_base64_decode((unsigned char *)encoded_cookie, encoded_len, (long *)&decoded_len);
+       if(decoded_len != SECURITY_SERVER_COOKIE_LEN)
+       {
+               printf("Base64 decode failed: %d\n", decoded_len);
+               exit(1);
+       }
+
+       if(decoded_cookie == NULL)
+       {
+               printf("%s", "BASE64 decode failed:\n");
+               exit(1);
+       }
+
+       memcpy(cookie, decoded_cookie, SECURITY_SERVER_COOKIE_LEN);
+       if(decoded_cookie != NULL)
+               free(decoded_cookie);
+
+       return;
+}
+
+void util_send_cookie_info_request_from_pid(const char *str_pid)
+{
+       int retval, sockfd, pid;
+
+       if(str_pid == NULL)
+       {
+               printf("Wrong PID\n");
+               return;
+       }
+
+       errno = 0;
+       pid = strtoul(str_pid, 0, 10);
+       if (errno != 0)
+       {
+               SEC_SVR_DBG("cannot change string to integer [%s]", str_pid);
+               return;
+       }
+
+       retval = connect_to_server(&sockfd);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               printf("Error: %s\n", "connection failed");
+               goto error;
+       }
+
+       /* make request packet */
+       retval = send_cookie_info_request_from_pid(sockfd, pid);
+       if(retval != SECURITY_SERVER_SUCCESS)
+       {
+               /* Error on socket */
+               SEC_SVR_DBG("Error: send request failed: %d", retval);
+               goto error;
+       }
+       retval = recv_cookie_info_response(sockfd);
+       if(retval == SECURITY_SERVER_ERROR_NO_SUCH_COOKIE)
+       {
+               printf("There is no such cookie available\n");
+               goto error;
+       }
+       if(retval <0)
+       {
+               printf("Error: Error receiving cookie info: %d\n", retval);
+               goto error;
+       }
+
+error:
+       if(sockfd > 0)
+       {
+               close(sockfd);
+       }
+       return;
+}
+
+int main(int argc, char *argv[])
+{
+       int ret;
+       unsigned char cookie[20];
+       ret = getuid();
+       if(ret != 0)
+       {
+               printf("You must be root to test. Current UID: %d\nExiting...\n", ret);
+               exit(1);
+       }
+       if(argc < 2 || argc > 4)
+       {
+               printf("Wrong usage: %d\n", argc);
+               printusage(argv[0]);
+               exit(1);
+       }
+       if(strcmp(argv[1], "-a") == 0)
+       {
+               if(argc != 2)
+               {
+                       printf("Wrong usage: %d\n", argc);
+                       printusage(argv[0]);
+                       exit(1);
+               }
+                       
+               util_send_all_cookie_info_request();
+               exit(0);
+       }
+
+       if(argc < 3)
+       {
+               printf("Wrong usage: %d\n", argc);
+               printusage(argv[0]);
+               exit(1);
+       }
+
+       if(strcmp(argv[1], "-f") == 0)
+       {
+               util_read_cookie_from_bin_file(cookie, argv[2]);
+               util_send_cookie_info_request_from_cookie(cookie);
+               exit(0);
+       }
+
+       if(strcmp(argv[1], "-p") == 0)
+       {
+               util_send_cookie_info_request_from_pid(argv[2]);
+               exit(0);
+       }
+
+       if(strcmp(argv[1], "-s") == 0)
+       {
+               util_read_cookie_from_base64_string(cookie, argv[2]);
+               util_send_cookie_info_request_from_cookie(cookie);
+               exit(0);
+       }
+
+       printf("%s", "Wrong usage\n");
+       printusage(argv[0]);
+       exit(1);
+}
diff --git a/testcases/debug-util.c b/testcases/debug-util.c
new file mode 100644 (file)
index 0000000..310f8be
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "security-server.h"
+#define DEVELOPER_UID 5100
+
+int main(int argc, char *argv[])
+{
+       int uid, ret, i;
+
+       uid = getuid();
+       if(uid == DEVELOPER_UID)
+       {
+               printf("Sending request to security server...\n");
+               ret = security_server_launch_debug_tool(argc -1, (const char **) argv + 1);
+               if(ret != SECURITY_SERVER_API_SUCCESS)
+               {
+                       printf("Failed to launch tool[%d]\n", ret);
+                       exit(-1);
+               }
+               exit(0);
+       }
+       if(uid == 0)
+       {
+               printf("%s", "This is executed as root privilege\n");
+               printf("argc = %d\n");
+               for(i=0;i<argc;i++)
+               {
+                       printf("argv[%d]: [%s]\n", i, argv[i]);
+               }
+               exit(0);
+       }
+       printf("Wrong uid: %d\n", uid);
+       printf("You must run %s under root user or developer(%d) user\n", argv[0], DEVELOPER_UID);
+       exit(-1);
+       
+}
diff --git a/testcases/security_server_tc_client.c b/testcases/security_server_tc_client.c
new file mode 100644 (file)
index 0000000..aa29375
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <fcntl.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include "security-server.h"
+#include "test.h"
+
+int *g_permissions = NULL;
+gid_t *g_groups = NULL;
+int g_perm_num, g_group_num;
+
+void printusage(char *cmdline)
+{
+       printf("%s\n", "Usage: ");
+       printf("%s -u uid -g gid1 gid2 gid3... -p gid_a gid_b gid_c ...\n", cmdline);
+       printf("%s\n", "[Options]");
+       printf("%s\n", "-u: UID that the process are running as");
+       printf("%s\n", "    Only one UID is allowed.");
+       printf("%s\n", "-g: GIDs that the process belongs to");
+       printf("%s\n", "-p: GIDs that the process wants to get privilege");
+       printf("%s\n", "Example:");
+       printf("%s -u 5000 -g 6001 6002 6003 6004 6005 6006 6007 -p 6001 6002 6010\n", cmdline);
+}
+
+int privilege_control(int argc, char *argv[])
+{
+       int option = 0; /* 0: no, 1: uID, 2: gid, 3: permission */
+       int uid_flag = 0, gid_flag= 0, perm_flag = 0, i = 1, number, uid = 0, j;
+
+       while(i < argc)
+       {
+               if(strcmp(argv[i], "-u") == 0)
+               {
+                       if(uid_flag != 0)
+                       {
+                               printf("%s\n", "-u option already used");
+                               printusage(argv[0]);
+                               exit(1);
+                       }
+                       option = 1;
+                       uid_flag = 1;
+               }
+               else if (strcmp(argv[i], "-g") == 0)
+               {
+                       if(gid_flag != 0)
+                       {
+                               printf("%s\n", "-g option already used");
+                               printusage(argv[0]);
+                               exit(1);
+                       }
+                       option = 2;
+                       gid_flag = 1;
+               }
+               else if (strcmp(argv[i], "-p") == 0)
+               {
+                       if(perm_flag != 0)
+                       {
+                               printf("%s\n", "-p option already used");
+                               printusage(argv[0]);
+                               exit(1);
+                       }
+                       option = 3;
+                       perm_flag = 1;
+               }
+               else
+               {
+                       errno = 0;
+                       number = strtoul(argv[i], 0, 10);
+                       if(errno != 0)
+                       {
+                               printf("%s\n", "Invalid option");
+                               printusage(argv[0]);
+                               exit(1);
+                       }
+                       switch(option)
+                       {
+                               case 1:
+                                       if(uid != 0)
+                                       {
+                                               printf("%s\n", "You cannot assign more than 1 uID");
+                                               printusage(argv[0]);
+                                               exit(1);
+                                       }
+                                       uid = number;
+                                       break;
+                               case 2:
+                                       for(j=0;i<g_group_num;j++)
+                                       {
+                                               if(number == g_groups[j])
+                                                       break;
+                                       }
+                                       g_groups = (gid_t *)realloc(g_groups, sizeof(gid_t) * (++g_group_num));
+                                       g_groups[g_group_num -1] = number;
+                                       break;
+                               case 3:
+                                       for(j=0;i<g_perm_num;j++)
+                                       {
+                                               if(number == g_permissions[j])
+                                                       break;
+                                       }
+                                       g_permissions = (int *)realloc(g_permissions, sizeof(int) * (++g_perm_num));
+                                       g_permissions[g_perm_num -1] = number;
+                                       break;
+                               default:
+                                       printf("%s\n", "Invalid option");
+                                       printusage(argv[0]);
+                                       exit(1);
+                                       break;
+                       }
+               }
+               i++;
+       }
+       if(g_group_num == 0 || g_perm_num == 0)
+       {
+               printf("%s\n", "You must assign groups and permissions");
+               printusage(argv[0]);
+               exit(1);
+       }
+       if(setgroups(g_group_num, g_groups) != 0)
+       {
+               printf("%s\n", "Error on setgroups{}");
+               exit(1);
+       }
+
+       setgid(uid);
+       setuid(uid);
+       return 0;
+}
+
+int connect_to_testserver()
+{
+       struct sockaddr_un clientaddr;
+       int client_len = 0, localsockfd, ret;
+
+       /* Create a socket */
+       if((localsockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+       {
+               printf("%s\n", "Error on socket()");
+               return 0;
+       }
+
+       bzero(&clientaddr, sizeof(clientaddr));
+       clientaddr.sun_family = AF_UNIX;
+       strncpy(clientaddr.sun_path, SECURITY_SERVER_TEST_SOCK_PATH, strlen(SECURITY_SERVER_TEST_SOCK_PATH));
+       clientaddr.sun_path[strlen(SECURITY_SERVER_TEST_SOCK_PATH)] = 0;
+       client_len = sizeof(clientaddr);
+       if(connect(localsockfd, (struct sockaddr*)&clientaddr, client_len) < 0)
+       {
+               printf("%s\n", "Error on connect");
+               close(localsockfd);
+               return 0;
+       }
+       return localsockfd;
+}
+
+void printhex(unsigned char *data, int size)
+{
+       int i;
+       for(i=0;i<size;i++)
+       {
+               if(data[i] < 0x10)
+                       printf("0");
+
+               printf("%X ", data[i]);
+               if(((i+1) % 16) == 0 && i != 0)
+                       printf("\n");
+       }
+       printf("\n");
+}
+
+
+int send_request(int sock_fd, unsigned char *cookie, int perm)
+{
+       unsigned char buf[28] = {0, 0, 0, 0, };
+       int size;
+       memcpy(buf + 4, cookie, 20);
+       memcpy(buf + 24, &perm, sizeof(int));
+       size = write(sock_fd, buf, 28);
+       if(size < 28)
+       {
+               printf("Cannot send\n");
+               close(sock_fd);
+               exit(1);
+       }
+       return 0;
+}
+
+
+int recv_result(int sock_fd)
+{
+       int buf, size;
+       size = read(sock_fd, &buf, sizeof(int));
+       if(size < sizeof(int))
+       {
+               printf("Cannot recv\n");
+               close(sock_fd);
+               exit(1);
+       }
+       return buf;
+}
+
+
+
+int main(int argc, char *argv[])
+{
+       int ret, sock_fd, i, cur_pid, cnt;
+       unsigned char cookie[20];
+       char tmpchar[100];
+
+       g_group_num = 0;
+       g_perm_num = 0;
+
+       ret = getuid();
+       if(ret != 0)
+       {
+               printf("You must be root to test. Current UID: %d\nExiting...\n", ret);
+               exit(1);
+       }
+
+       if(argc < 2)
+       {
+               printf("%s\n", "Error: No group identified");
+               printusage(argv[0]);
+               exit(1);
+       }
+
+       system("touch /opt/home/root/pid_cycle");
+       privilege_control(argc, argv);
+
+       printf("Strting test. My PID is %d\n", getpid());
+
+       printf("TC C1: security_server_get_cookie_size()\n");
+       ret = security_server_get_cookie_size();
+       if(ret != 20)
+       {
+               printf("TC C1 failed. %d\n", ret);
+               exit(1);
+
+       }
+       printf("TC C1: PASSED\n\n");
+       sleep(1);
+
+       printf("TC C2: security_server_request_cookie(): normal case\n");
+       ret = security_server_request_cookie(cookie, 20);
+       if(ret != SECURITY_SERVER_API_SUCCESS)
+       {
+               printf("TC C2 failed. %d\n", ret);
+               exit(1);
+       }
+       printhex(cookie, 20);
+       printf("TC C2: PASSED\n\n");
+       sleep(1);
+
+       printf("TC C3: security_server_request_cookie(): Too small buffer size\n");
+       ret = security_server_request_cookie(cookie, 10);
+       if(ret != SECURITY_SERVER_API_ERROR_BUFFER_TOO_SMALL)
+       {
+               printf("TC C3 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("TC C3: PASSED\n\n");
+       sleep(1);
+
+       printf("TC C4: security_server_check_privilege(): client is not allowed\n");
+       ret = security_server_check_privilege(cookie, g_permissions[0]);
+       if(ret != SECURITY_SERVER_API_ERROR_AUTHENTICATION_FAILED)
+       {
+               printf("TC C4 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("TC C4: PASSED\n\n");
+       sleep(1);
+
+       printf("TC C5: security_server_get_gid(): client is not allowed\n");
+       ret = security_server_get_gid("telephony");
+       if(ret != SECURITY_SERVER_API_ERROR_AUTHENTICATION_FAILED)
+       {
+               printf("TC C5 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("TC C5: PASSED\n\n");
+       sleep(1);
+
+       printf("TC C6: security_server_get_object_name(): client is not allowed\n");
+       ret = security_server_get_object_name(g_groups[0], tmpchar, sizeof(tmpchar));
+       if(ret != SECURITY_SERVER_API_ERROR_AUTHENTICATION_FAILED)
+       {
+               printf("TC C6 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("TC C6: PASSED\n\n");
+       sleep(1);
+
+       printf("TC C7: Requesting access to test server\n");
+       for(i=0;i<g_perm_num;i++)
+       {
+               sock_fd = connect_to_testserver();
+               if(sock_fd < 1)
+               {
+                       printf("Socket connection error\n");
+                       exit(1);
+               }
+               printf("%d: requesting %d permission...sockfd=%d\n", i, g_permissions[i], sock_fd);
+               ret = send_request(sock_fd, cookie, g_permissions[i]);
+               if(ret != 0)
+               {
+                       printf("send failed\n");
+                       close(sock_fd);
+                       exit(1);
+               }
+
+               ret = recv_result(sock_fd);
+               if(ret == SECURITY_SERVER_API_SUCCESS)
+               {
+                       printf("Permission granted\n\n");
+               }
+               else if(ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED)
+               {
+                       printf("Permission denied\n\n");
+               }
+               else
+               {
+                       printf("Recv error\n");
+                       close(sock_fd);
+                       exit(1);
+               }
+               close(sock_fd);
+               sock_fd = 0;
+       }
+       sleep(1);
+       printf("TC 08: Requesting cookie for same PID with different path\n");
+       printf("       Exiting this process to cycle different process as same PID.\n");
+       printf("       Please look at the test server's terminal for the result\n");
+       cur_pid = getpid();
+       sock_fd = connect_to_testserver();
+       if(sock_fd < 1)
+       {
+               printf("Socket connection error\n");
+               exit(1);
+       }
+
+       unsigned char buf[32] = {255, 255, 255, 255, };
+       int size;
+
+       memcpy(buf + 4, cookie, 20);
+       memcpy(buf + 24, &cur_pid, sizeof(int));
+       ret = getuid();
+       memcpy(buf + 28, &ret, sizeof(int));
+
+       size = write(sock_fd, buf, 32);
+       if(size < 32)
+       {
+               printf("Cannot send\n");
+               close(sock_fd);
+               exit(1);
+       }
+       if(sock_fd > 0)
+               close(sock_fd);
+       if(g_groups != NULL)
+               free(g_groups);
+       if(g_permissions != NULL)
+               free(g_permissions);
+       return 0;
+}
+
diff --git a/testcases/security_server_tc_password.c b/testcases/security_server_tc_password.c
new file mode 100644 (file)
index 0000000..721d2dd
--- /dev/null
@@ -0,0 +1,540 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <fcntl.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <dirent.h>
+#include "security-server.h"
+#include "test.h"
+
+void printusage(char *cmdline)
+{
+       printf("%s\n", "Usage: ");
+       printf("%s password1, password2\n", cmdline);
+       printf("%s\n", "Example:");
+       printf("%s 123456 abcdef\n", cmdline);
+}
+
+void printhex(unsigned char *data, int size)
+{
+       int i;
+       for(i=0;i<size;i++)
+       {
+               if(data[i] < 0x10)
+                       printf("0");
+
+               printf("%X ", data[i]);
+               if(((i+1) % 16) == 0 && i != 0)
+                       printf("\n");
+       }
+       printf("\n");
+}
+
+int dir_filter(const struct dirent *entry)
+{
+       if ((strcmp(entry->d_name, ".") == 0) || 
+               (strcmp(entry->d_name, "..") == 0) ||
+               (strcmp(entry->d_name, "attempts") ==0) ||
+               (strcmp(entry->d_name, "history") ==0) )
+               return (0);
+       else
+               return (1);
+}
+
+int main(int argc, char *argv[])
+{
+       int ret;
+       unsigned long i=1;
+       unsigned int attempt, max_attempt, expire_sec, temp_sec;
+       struct timeval cur_time;
+       char buf1[33], buf2[33];
+       struct dirent **mydirent;
+
+       if(argc < 2)
+       {
+               printf("%s\n", "Error: No password identified");
+               printusage(argv[0]);
+               exit(1);
+       }
+
+       if(getuid() == 0)
+       {
+               system("rm /opt/data/security-server/*");
+               sync();
+
+               printf("TC P1: security_server_is_pwd_empty(). no pwd case.\n");
+               ret = security_server_is_pwd_valid(&attempt, &max_attempt, &expire_sec);
+               if(ret != SECURITY_SERVER_API_ERROR_NO_PASSWORD || attempt != 0 || max_attempt != 0 || expire_sec != 0)
+               {
+                       printf("TC P1 failed. return = %d, current_attempt=%d, max_attempt=%d, expire_day=%d\n", ret, attempt, max_attempt, expire_sec);
+                       exit(1);
+               }
+               printf("TC P1: PASSED\n\n");
+               sleep(1);
+       }
+       else
+       {
+               printf("To run the TC as non root user, please remove password files (/opt/data/security-server/*) in root shell\n");
+               printf("If not, you will see some TC failures\n");
+       }
+
+       printf("TC P2: security_server_chk_pwd(): Too long password case\n");
+       ret = security_server_chk_pwd("abcdefghijklmnopqrstuvwxyz0123456", &attempt, &max_attempt, &expire_sec); /* 33 chars */
+       if(ret != SECURITY_SERVER_API_ERROR_INPUT_PARAM)
+       {
+               printf("TC P2 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("TC P2: PASSED\n\n");
+       sleep(1);
+
+       printf("TC P3: security_server_chk_pwd(): NULL input case\n");
+       ret = security_server_chk_pwd(NULL, &attempt, &max_attempt, &expire_sec);
+       if(ret != SECURITY_SERVER_API_ERROR_INPUT_PARAM)
+       {
+               printf("TC P3.1 failed. %d\n", ret);
+               exit(1);
+       }
+       ret = security_server_chk_pwd("password", NULL, &max_attempt, &expire_sec);
+       if(ret != SECURITY_SERVER_API_ERROR_INPUT_PARAM)
+       {
+               printf("TC P3.2 failed. %d\n", ret);
+               exit(1);
+       }
+       ret = security_server_chk_pwd("password", &attempt, NULL, &expire_sec);
+       if(ret != SECURITY_SERVER_API_ERROR_INPUT_PARAM)
+       {
+               printf("TC P3.3 failed. %d\n", ret);
+               exit(1);
+       }
+       ret = security_server_chk_pwd("password", &attempt, &max_attempt, NULL);
+       if(ret != SECURITY_SERVER_API_ERROR_INPUT_PARAM)
+       {
+               printf("TC P3.4 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("TC P3: PASSED\n\n");
+       sleep(1);
+
+       printf("TC P4: security_server_chk_pwd(): no password case\n");
+       ret = security_server_chk_pwd("isthisempty", &attempt, &max_attempt, &expire_sec);
+       if(ret != SECURITY_SERVER_API_ERROR_NO_PASSWORD || max_attempt != 0 || expire_sec != 0)
+       {
+               printf("TC P4 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("TC P4: PASSED\n\n");
+       sleep(1);
+
+       printf("TC P5: security_server_set_pwd(): NULL input case\n");
+       ret = security_server_set_pwd(NULL, NULL, 0, 0);
+       if(ret != SECURITY_SERVER_API_ERROR_INPUT_PARAM)
+       {
+               printf("TC P5 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("TC P5: PASSED\n\n");
+       sleep(1);
+
+       printf("TC P6: security_server_set_pwd(): Too long input param\n");
+       ret = security_server_set_pwd("abcdefghijklmnopqrstuvwxyz0123456", "abcdefghijklmnopqrstuvwxyz0123456", 0, 0);
+       if(ret != SECURITY_SERVER_API_ERROR_INPUT_PARAM)
+       {
+               printf("TC P6 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("TC P6: PASSED\n\n");
+       sleep(1);
+
+       printf("TC P7: security_server_set_pwd(): Normal case when current pwd is empty\n");
+       ret = security_server_set_pwd(NULL, argv[1], 0, 0);
+       if(ret != SECURITY_SERVER_API_SUCCESS)
+       {
+               printf("TC P7 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("TC P7: PASSED\n\n");
+       sleep(1);
+
+       printf("TC P8: security_server_chk_pwd(): normal(correct pwd) case\n");
+       ret = security_server_chk_pwd(argv[1], &attempt, &max_attempt, &expire_sec);
+       if(ret != SECURITY_SERVER_API_SUCCESS)
+       {
+               printf("TC P8 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("TC P8: PASSED\n\n");
+       sleep(1);
+
+       printf("TC P9: security_server_is_pwd_empty(). password exists.\n");
+       ret = security_server_is_pwd_valid(&attempt, &max_attempt, &expire_sec);
+       if(ret != SECURITY_SERVER_API_ERROR_PASSWORD_EXIST)
+       {
+               printf("TC P9 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("TC P9: PASSED\n\n");
+       sleep(1);
+       
+       printf("TC P10: security_server_chk_pwd(): incorrect pwd case\n");
+       (argv[1])[0]++;
+       ret = security_server_chk_pwd(argv[1], &attempt, &max_attempt, &expire_sec);
+       if(ret != SECURITY_SERVER_API_ERROR_PASSWORD_MISMATCH)
+       {
+               printf("TC P10 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("TC P10: PASSED\n\n");
+       sleep(1);
+
+       printf("TC P11: security_server_set_pwd(): Incorrect current password\n");
+       ret = security_server_set_pwd(argv[1], argv[2], 0, 0);
+       if(ret != SECURITY_SERVER_API_ERROR_PASSWORD_MISMATCH)
+       {
+               printf("TC P11 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("TC P11: PASSED\n\n");
+       (argv[1])[0]--;
+       sleep(1);
+
+       printf("TC P12: security_server_set_pwd(): correct password\n");
+       ret = security_server_set_pwd(argv[1], argv[2], 0, 0);
+       if(ret != SECURITY_SERVER_API_SUCCESS)
+       {
+               printf("TC P12 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("TC P12: PASSED\n\n");
+       sleep(1);
+
+       printf("TC P13: security_server_chk_pwd(): Check increasing attempts, with reset when correct password has been checked\n");
+       ret = security_server_set_pwd(argv[2], argv[1], 10, 0);
+       if(ret != SECURITY_SERVER_API_SUCCESS)
+       {
+               printf("TC P13.1 failed. %d\n", ret);
+               exit(1);
+       }
+       sleep(1);
+       for(i=0;i<5;i++)
+       {
+               printf("%d\n", i+1);
+               ret = security_server_chk_pwd(argv[2],  &attempt, &max_attempt, &expire_sec);
+               if(ret != SECURITY_SERVER_API_ERROR_PASSWORD_MISMATCH)
+               {
+                       printf("\nTC P13.%da failed. %d\n", i+2, ret);
+                       exit(1);
+               }
+               if(attempt != (i+1))
+               {
+                       printf("\nTC P13.%db failed. %d\n", i+2, ret);
+                       exit(1);
+               }
+               sleep(1);
+       }
+       printf("%d\n", i+1);
+       ret = security_server_chk_pwd(argv[1],  &attempt, &max_attempt, &expire_sec);
+       if(ret != SECURITY_SERVER_API_SUCCESS)
+       {
+               printf("TC P13.%d failed. %d\n", i+2, ret);
+               exit(1);
+       }
+       sleep(1);
+       printf("%d\n", i+2);
+       ret = security_server_is_pwd_valid(&attempt, &max_attempt, &expire_sec);
+       if(ret != SECURITY_SERVER_API_ERROR_PASSWORD_EXIST)
+       {
+               printf("TC P13.%d failed. %d\n", i+3, ret);
+               exit(1);
+       }
+       if(attempt != 0 || max_attempt != 10)
+       {
+               printf("TC P13.%d failed. %d\n", i+3, ret);
+               exit(1);
+       }
+       printf("TC P13: PASSED\n\n");
+       sleep(1);       
+
+       printf("TC P14: security_server_chk_pwd(): attempt exceeding case\n");
+       for(i=0;i<10;i++)
+       {
+               printf("%d\n", i+1);
+               ret = security_server_chk_pwd(argv[2],  &attempt, &max_attempt, &expire_sec);
+               if(ret != SECURITY_SERVER_API_ERROR_PASSWORD_MISMATCH)
+               {
+                       printf("\nTC P14.%da failed. %d\n", i+1, ret);
+                       exit(1);
+               }
+               if(attempt != (i+1))
+               {
+                       printf("\nTC P14.%db failed. %d\n", i+1, ret);
+                       exit(1);
+               }
+               sleep(1);
+       }
+       printf("%d\n", i+1);
+       ret = security_server_chk_pwd(argv[1],  &attempt, &max_attempt, &expire_sec);
+       if(ret != SECURITY_SERVER_API_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED)
+       {
+               printf("TC P14.%d failed. %d\n", i+1, ret);
+               exit(1);
+       }
+       printf("TC P14: PASSED\n\n");
+       sleep(1);       
+
+       printf("TC P15: security_server_reset_pwd(): Reset current password\n");
+       ret = security_server_reset_pwd(argv[1],0, 0);
+       if(ret != SECURITY_SERVER_API_SUCCESS)
+       {
+               printf("TC P15 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("TC P15: PASSED\n\n");
+       sleep(1);       
+
+       printf("TC P16: security_server_set_pwd(): Check expiration \n");
+       ret = security_server_set_pwd(argv[1], argv[2], 10, 1);
+       if(ret != SECURITY_SERVER_API_SUCCESS)
+       {
+               printf("TC P16.1 failed. %d\n", ret);
+               exit(1);
+       }
+       sleep(1);
+       ret = security_server_is_pwd_valid(&attempt, &max_attempt, &expire_sec);
+       if(ret != SECURITY_SERVER_API_ERROR_PASSWORD_EXIST)
+       {
+               printf("TC P16.2 failed. %d\n", ret);
+               exit(1);
+       }
+       if(expire_sec > 86400 || expire_sec < 86398)
+       {
+               printf("TC P16.3 failed. %d, %d\n", ret, expire_sec);
+               exit(1);
+       }
+       printf("TC P16: PASSED\n\n");
+       sleep(1);       
+
+       printf("TC P17: security_server_chk_pwd(): Check expiration sec decreasing\n");
+       ret = security_server_is_pwd_valid(&attempt, &max_attempt, &expire_sec);
+       if(ret != SECURITY_SERVER_API_ERROR_PASSWORD_EXIST)
+       {
+               printf("TC P17.1 failed. %d\n", ret);
+               exit(1);
+       }
+       sleep(1);
+       temp_sec = 0;
+       for(i=0;i<5;i++)
+       {
+               expire_sec = 0;
+               ret = security_server_chk_pwd(argv[2],  &attempt, &max_attempt, &expire_sec);
+               if(ret != SECURITY_SERVER_API_SUCCESS)
+               {
+                       printf("\nTC P17.%da failed. %d\n", i+4, ret);
+                       exit(1);
+               }
+               if(temp_sec != 0 && ((temp_sec -expire_sec) > 2) && ((temp_sec -expire_sec) < 1))
+               {
+                       printf("\nTC P17.%db failed. %d, %d, %d\n", i+4, ret, temp_sec, expire_sec);
+                       exit(1);
+               }
+               temp_sec = expire_sec;
+               printf("%d\n", expire_sec);
+               sleep(1);
+       }
+       printf("\nTC P17: PASSED\n\n");
+       
+       printf("TC P18: security_server_chk_pwd(): Check expiration with system time change\n");
+       ret = gettimeofday(&cur_time, NULL);
+       if(ret < 0)
+       {
+               printf("TC P18.1 failed. %d\n", ret);
+               exit(1);
+       }
+       cur_time.tv_sec += (expire_sec -4);
+       ret = settimeofday(&cur_time, NULL);
+       if(ret < 0)
+       {
+               printf("TC P18.2 failed. %d\n", ret);
+               exit(1);
+       }
+       temp_sec = 0;
+       for(i=0;i<5;i++)
+       {
+               expire_sec = 0;
+               ret = security_server_chk_pwd(argv[2],  &attempt, &max_attempt, &expire_sec);
+               if(ret != SECURITY_SERVER_API_SUCCESS && ret != SECURITY_SERVER_API_ERROR_PASSWORD_EXPIRED)
+               {
+                       printf("\nTC P18.%da failed. %d\n", i+1, ret);
+                       exit(1);
+               }
+               if(ret == SECURITY_SERVER_API_ERROR_PASSWORD_EXPIRED)
+                       break;
+
+               if(temp_sec != 0 && ((temp_sec -expire_sec) > 2) && ((temp_sec -expire_sec) < 1))
+               {
+                       printf("\nTC P18.%db failed. %d, %d, %d\n", i+1, ret, temp_sec, expire_sec);
+                       exit(1);
+               }
+               temp_sec = expire_sec;
+               printf("%d\n", expire_sec);
+               sleep(1);
+       }
+       if(ret != SECURITY_SERVER_API_ERROR_PASSWORD_EXPIRED)
+       {
+               printf("\nTC P18.%i failed. %d\n", i+1, ret);
+               exit(1);
+       }
+       printf("\nTC P18: PASSED\n\n");
+       sleep(1);
+
+       printf("TC P19: security_server_set_pwd_history(): Too big & small number\n");
+       ret = security_server_set_pwd_history(100);
+       if(ret != SECURITY_SERVER_API_ERROR_INPUT_PARAM)
+       {
+               printf("\nTC P19.1 failed. %d\n", ret);
+               exit(1);
+       }
+       ret = security_server_set_pwd_history(-5);
+       if(ret != SECURITY_SERVER_API_ERROR_INPUT_PARAM)
+       {
+               printf("\nTC P19.2 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("\nTC P19: PASSED\n\n");
+       sleep(1);
+
+       printf("TC P20: security_server_set_pwd_history(): normal case\n");
+       ret = security_server_set_pwd_history(10);
+       if(ret != SECURITY_SERVER_API_SUCCESS)
+       {
+               printf("\nTC P20 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("\nTC P20: PASSED\n\n");
+       sleep(1);
+
+       printf("TC P21: security_server_set_pwd_history(): Check history is working\n");
+       ret = security_server_reset_pwd("history1",0, 0);
+       if(ret != SECURITY_SERVER_API_SUCCESS)
+       {
+               printf("TC P21.1 failed. %d\n", ret);
+               exit(1);
+       }
+       printf("1\n");
+       sleep(1);
+       for(i=1;i<11;i++)
+       {
+               sprintf(buf1, "history%d", i);
+               sprintf(buf2, "history%d", i+1);
+               ret = security_server_set_pwd(buf1, buf2, 0, 0);
+               if(ret != SECURITY_SERVER_API_SUCCESS)
+               {
+                       printf("\nTC P21.%d failed. %d\n", i+1, ret);
+                       exit(1);
+               }
+               printf("%d\n", i+1);
+               sleep(1);
+       }
+       ret = security_server_set_pwd("history11", "history1", 0, 0);
+       if(ret != SECURITY_SERVER_API_SUCCESS)
+       {
+               printf("\nTC P21.%d failed. %d\n", i+1, ret);
+               exit(1);
+       }
+       sleep(1);
+       ret = security_server_set_pwd("history1", "history8", 0, 0);
+       if(ret != SECURITY_SERVER_API_ERROR_PASSWORD_REUSED)
+       {
+               printf("\nTC P21.%d failed. %d\n", i+2, ret);
+               exit(1);
+       }
+       printf("\nTC P21: PASSED\n\n");
+       sleep(1);
+
+       printf("TC P22: security_server_set_pwd(): Check Garbage collection\n");
+       ret = security_server_set_pwd("history1", "history12", 0, 0);
+       sprintf(buf1, "history12");
+       if(ret != SECURITY_SERVER_API_SUCCESS)
+       {
+               printf("\nTC P22.1 failed. %d\n", i+1, ret);
+               exit(1);
+       }
+       printf("12\n");
+       sleep(1);
+       for(i=12;i<60;i++)
+       {
+               sprintf(buf1, "history%d", i);
+               sprintf(buf2, "history%d", i+1);
+               ret = security_server_set_pwd(buf1, buf2, 0, 0);
+               if(ret != SECURITY_SERVER_API_SUCCESS)
+               {
+                       printf("\nTC P22.%d failed. %d\n", i+1, ret);
+                       exit(1);
+               }
+               printf("%d\n", i+1);
+               sleep(1);
+       }
+       ret = scandir("/opt/data/security-server", &mydirent, &dir_filter, alphasort);
+       i = ret;
+       while((i--))
+       {
+               free(mydirent[i]);
+       }
+       free(mydirent);
+       if( ret == 50 || ret == 51)
+       {
+               printf("\nTC P22: PASSED\n\n");
+               sleep(1);
+       }
+       else
+       {
+               printf("\nTC P22 failed. %d", ret);
+               exit(1);
+       }
+       printf("TC P23: security_server_chk_pwd(): incorrect with replay attack\n");
+       ret = security_server_chk_pwd("quickquickquick", &attempt, &max_attempt, &expire_sec);
+       do 
+       {
+               i =  i + 100000;
+               ret = security_server_chk_pwd("quickquickquick", &attempt, &max_attempt, &expire_sec);
+               usleep(i);
+       }
+       while(ret == SECURITY_SERVER_API_ERROR_PASSWORD_RETRY_TIMER);
+
+       if(ret != SECURITY_SERVER_API_ERROR_PASSWORD_MISMATCH )
+       {
+               printf("TC P23 failed[1]. %d\n", ret);
+               exit(1);
+       }
+       i = i - 100000;
+       printf("Last interval was %d.%06d sec.\n", (i /1000000), (i % 1000000) );
+       printf("TC P23: PASSED\n\n");
+
+       return 0;
+}
+
diff --git a/testcases/security_server_tc_pid_reuser.c b/testcases/security_server_tc_pid_reuser.c
new file mode 100644 (file)
index 0000000..8971085
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "security-server.h"
+#include "test.h"
+
+void printusage(const char *cmdline)
+{
+       printf("%s\n", "Usage: ");
+       printf("%s [uid] [pid] [hexa decimal cookie]\n", cmdline);
+       printf("%s\n", "[pid]: PID want to be reused");
+       printf("%s\n", "[hexa decimal cookie]: Cookie value which is issued to the previous process with the [pid] for comparison\nThe cookie must be hexa decimal, with lower case and without whitespace and new line characters\n");
+       printf("%s\n", "* This test program must be executed as root process");
+}
+
+void printhex(unsigned char *data, int size)
+{
+       int i;
+       for(i=0;i<size;i++)
+       {
+               if(data[i] < 0x10)
+                       printf("0");
+
+               printf("%X ", data[i]);
+               if(((i+1) % 16) == 0 && i != 0)
+                       printf("\n");
+       }
+       printf("\n");
+}
+
+void convert_prev_cookie(const char *cmdline, const char *prev, unsigned char *now)
+{
+       int i, cnt;
+       char tmphexnum[3] = {0};
+       cnt = security_server_get_cookie_size();
+       cnt = cnt * 2;
+       if(strlen(prev) != cnt)
+       {
+               printf("%s\n", "Cookie lenth is wrong");
+               printusage(cmdline);
+               exit(1);
+       }
+
+       for(i=0, cnt=0 ; i<strlen(prev) ; i=i+2)
+       {
+               strncpy(tmphexnum, prev+i, 2);
+               tmphexnum[2] = 0;
+               errno = 0;
+               now[cnt] = strtoul(tmphexnum, 0, 16);
+               if(errno != 0)
+               {
+                       printf("%s\n", "cannot convert hex cookie to binary");
+                       printusage(cmdline);
+                       exit(1);
+               }
+               cnt++;
+       }
+}
+
+void check_status()
+{
+       struct stat statbuf;
+       int ret;
+       ret = stat("/opt/home/root/pid_cycle", &statbuf);
+       if(ret != 0)
+       {
+               printf("Interrupt encountered. exiting...\n");
+               exit(0);
+       }
+       
+}
+
+void cycle_pid(int pid)
+{
+       int cur_pid = getpid();
+       int dotval;
+       
+       while(cur_pid != pid)
+       {
+               if(fork() != 0)
+               {
+                       dotval = cur_pid % 1000;
+                       if(dotval == 0)
+                               printf(".");
+                       exit(0);
+               }
+               cur_pid = getpid();
+               check_status();
+       }
+}
+
+int main(int argc, char *argv[])
+{
+       int ret, sock_fd, cookie_size, target_pid, target_uid;
+
+       target_uid = getuid();
+       if(target_uid != 0)
+       {
+               printusage(argv[0]);
+               exit(1);
+       }
+
+       cookie_size = security_server_get_cookie_size();
+       unsigned char prev_cookie[cookie_size], new_cookie[cookie_size];
+
+       if(argc < 3)
+       {
+               printusage(argv[0]);
+               exit(1);
+       }
+
+       errno = 0;
+       target_uid = strtoul(argv[1], 0, 10);
+       if(errno != 0)
+       {
+               printf("%s\n", "cannot convert string uid to integer");
+               printusage(argv[0]);
+               exit(1);
+       }
+       printf("Target UID is %d. change user...\n", target_uid);
+       setuid(target_uid);
+
+       errno = 0;
+       target_pid = strtoul(argv[2], 0, 10);
+       if(errno != 0)
+       {
+               printf("%s\n", "cannot convert string pid to integer");
+               printusage(argv[0]);
+               exit(1);
+       }
+       convert_prev_cookie(argv[0], argv[3], prev_cookie);
+       check_status();
+
+       printf("Cycling PID to %d\n", target_pid);
+
+       cycle_pid(target_pid);
+       unlink("/opt/home/root/pid_cycle");
+
+       ret = security_server_request_cookie(new_cookie, 20);
+       if(ret != SECURITY_SERVER_API_SUCCESS)
+       {
+               printf("get cookie failed. %d\n", ret);
+               exit(1);
+       }
+       printf("\nTarget PID: %d, Target UID: %d\n", target_pid, target_uid);
+       printf("Previous cookie:\n");
+       printhex(prev_cookie, 20);
+       printf("Newly issued cookie:\n");
+       printhex(new_cookie, 20);
+       
+       if(memcmp(prev_cookie, new_cookie, cookie_size) == 0)
+       {
+               printf("TC failed. same cookie\n");
+               exit(1);
+       }
+       
+       printf("TC C8: PASSED\n");
+       return 0;
+}
+
diff --git a/testcases/security_server_tc_server.c b/testcases/security_server_tc_server.c
new file mode 100644 (file)
index 0000000..7ca4f34
--- /dev/null
@@ -0,0 +1,645 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <fcntl.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <poll.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include "security-server.h"
+#include "test.h"
+
+
+#define SECURITY_SERVER_SOCK_PATH      "/tmp/.security_server.sock"
+
+/* Message */
+typedef struct
+{
+       unsigned char version;
+       unsigned char msg_id;
+       unsigned short msg_len;
+} basic_header;
+
+typedef struct
+{
+       basic_header basic_hdr;
+       unsigned char return_code;
+} response_header;
+
+
+/* Create a Unix domain socket and bind */
+int create_new_socket()
+{
+       int localsockfd = 0, flags;
+       struct sockaddr_un serveraddr;
+       mode_t sock_mode;
+
+       remove(SECURITY_SERVER_TEST_SOCK_PATH);
+
+       /* Create Unix domain socket */
+       if((localsockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0 )
+       {
+               localsockfd = -1;
+               printf("%s\n", "Socket creation failed");
+               goto error;
+       }
+
+       /* Make socket as non blocking */
+       if((flags = fcntl(localsockfd, F_GETFL, 0)) < 0 ||
+                       fcntl(localsockfd, F_SETFL, flags | O_NONBLOCK) < 0)
+       {
+               close(localsockfd);
+               localsockfd = -1;
+               printf("%s\n", "Cannot go to nonblocking mode");
+               goto error;
+       }
+
+       bzero (&serveraddr, sizeof(serveraddr));
+       serveraddr.sun_family = AF_UNIX;
+       strncpy(serveraddr.sun_path, SECURITY_SERVER_TEST_SOCK_PATH,
+                       strlen(SECURITY_SERVER_TEST_SOCK_PATH) + 1);
+
+       /* Bind the socket */
+       if((bind(localsockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
+       {
+               printf("%s\n", "Cannot bind");
+               close(localsockfd);
+               localsockfd = -1;
+               goto error;
+       }
+
+       /* Change permission to accept all processes that has different uID/gID */
+       sock_mode = (S_IRWXU | S_IRWXG | S_IRWXO);
+       /* Flawfinder hits this chmod function as level 5 CRITICAL as race condition flaw *
+        * Flawfinder recommends to user fchmod insted of chmod
+        * But, fchmod doesn't work on socket file so there is no other choice at this point */
+       if(chmod(SECURITY_SERVER_TEST_SOCK_PATH, sock_mode) < 0)                /* Flawfinder: ignore */
+       {
+               printf("%s\n", "chmod() error");
+               close(localsockfd);
+               localsockfd = -1;
+               goto error;
+       }
+error:
+       return localsockfd;
+}
+
+void printhex(unsigned char *data, int size)
+{
+       int i;
+       for(i=0;i<size;i++)
+       {
+               if(data[i] < 0x10)
+                       printf("0");
+
+               printf("%X ", data[i]);
+               if(((i+1) % 16) == 0 && i != 0)
+                       printf("\n");
+       }
+       printf("\n");
+}
+
+int check_socket_poll(int sockfd, int event, int timeout)
+{
+       struct pollfd poll_fd[1];
+       int retval;
+
+       poll_fd[0].fd = sockfd;
+       poll_fd[0].events = event;
+       retval = poll(poll_fd, 1, timeout);
+       if(retval < 0)
+       {
+               printf("%s", "poll() error");
+               return -1;
+       }
+
+       /* Timed out */
+       if(retval == 0)
+       {
+               /*SEC_SVR_DBG("%s", "poll() timeout");*/
+               return 0;
+       }
+       return 1;
+}
+
+int send_gid_request(int sock_fd, const char* object)
+{
+       basic_header hdr;
+       int retval, send_len = 0;
+       unsigned char *buf = NULL;
+
+       hdr.version = 0x01; /* SECURITY_SERVER_MSG_VERSION; */
+       hdr.msg_id = 0x07; /* SECURITY_SERVER_MSG_TYPE_GID_REQUEST; */
+       hdr.msg_len = strlen(object);
+
+       send_len = sizeof(hdr) + strlen(object);
+
+       buf = malloc(send_len);
+       if(buf == NULL)
+       {
+               printf("%s", "out of memory");
+               return -1;
+       }
+
+       memcpy(buf, &hdr, sizeof(hdr));
+       memcpy(buf + sizeof(hdr), object, strlen(object));
+
+       /* Check poll */
+       retval = check_socket_poll(sock_fd, POLLOUT, 1000);
+       if(retval == -1)
+       {
+               printf("%s", "poll() error");
+               if(buf != NULL)
+                       free(buf);
+               return -1;
+       }
+       if(retval == 0)
+       {
+               printf("%s", "poll() timeout");
+               if(buf != NULL)
+                       free(buf);              
+               return -1;
+       }
+
+       retval = write(sock_fd, buf, send_len);
+       if(retval < send_len)
+       {
+               /* Write error */
+               printf("Error on write(): %d. errno=%d, sockfd=%d", retval, errno, sock_fd);
+               if(buf != NULL)
+                       free(buf);
+               return -1;
+       }
+       if(buf != NULL)
+               free(buf);
+
+       return 0;       
+}
+
+int connect_to_server(int *fd)
+{
+       struct sockaddr_un clientaddr;
+       int client_len = 0, localsockfd, ret, flags;
+       *fd = -1;
+
+       /* Create a socket */
+       localsockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+       if(localsockfd < 0)
+       {
+               printf("%s", "Error on socket()");
+               return -1;
+       }
+
+       /* Make socket as non blocking */
+       if((flags = fcntl(localsockfd, F_GETFL, 0)) < 0 || 
+                       fcntl(localsockfd, F_SETFL, flags | O_NONBLOCK) < 0)
+       {
+               close(localsockfd);
+               printf("%s", "Cannot go to nonblocking mode");
+               return -1;
+       }
+
+       bzero(&clientaddr, sizeof(clientaddr));
+       clientaddr.sun_family = AF_UNIX;
+       strncpy(clientaddr.sun_path, SECURITY_SERVER_SOCK_PATH, strlen(SECURITY_SERVER_SOCK_PATH));
+       clientaddr.sun_path[strlen(SECURITY_SERVER_SOCK_PATH)] = 0;
+       client_len = sizeof(clientaddr);
+
+       ret = connect(localsockfd, (struct sockaddr*)&clientaddr, client_len);
+       if( ret < 0)
+       {
+               if(errno == EINPROGRESS)
+               {
+                       printf("%s", "Connection is in progress");
+                       check_socket_poll(localsockfd, POLLOUT, 1000);
+                       if(ret == -1)
+                       {
+                               printf("%s", "poll() error");
+                               close(localsockfd);
+                               return -1;
+                       }
+                       if(ret == 0)
+                       {
+                               printf("%s", "poll() timeout");
+                               close(localsockfd);
+                               return -1;
+                       }
+                       ret = connect(localsockfd, (struct sockaddr*)&clientaddr, client_len);
+                       if(ret < 0)
+                       {
+                               printf("%s", "connection failed");
+                               close(localsockfd);
+                               return -1;
+                       }
+               }
+               else
+               {
+                       printf("%s", "Connection failed");
+                       close(localsockfd);
+                       return -1;
+               }
+       }
+
+       *fd = localsockfd;
+       return 0;
+}
+
+
+int fake_get_gid(const char *object)
+{
+        int sockfd = -1, retval, gid;
+     response_header hdr;
+     retval = connect_to_server(&sockfd);
+     if(retval != 0)
+     {
+         /* Error on socket */
+         printf("Connection failed: %d", retval);
+         goto error;
+     }
+    /* make request packet and send to server*/
+     retval = send_gid_request(sockfd, object);
+     if(retval != 0)
+     {
+         /* Error on socket */
+         printf("Send request failed: %d", retval);
+         goto error;
+     }
+        printf("%s", "Just closing the socket and exit\n");
+
+error:
+        if(sockfd > 0)
+                close(sockfd);
+
+        return 0;
+}
+
+
+int main(int argc, char *argv[])
+{
+       int server_sockfd, client_sockfd, ret, recved_gid, client_len, i;
+       unsigned char cookie[20], recved_cookie[20], recvbuf[33], wrong_cookie[20];
+       char obj_name[30];
+       struct pollfd accept_poll[1], client_poll[1];
+       struct sockaddr_un clientaddr;
+       
+
+       ret = getuid();
+       if(ret != 0)
+       {
+               printf("TC must be executed by root\n");
+               exit(1);
+       }
+
+       printf("TC S1: Getting default cookie\n");
+       ret = security_server_request_cookie(cookie, 20);
+       if(ret != SECURITY_SERVER_API_SUCCESS)
+       {
+               printf("TC S1 failed to get cookie. %d\n", ret);
+               exit(1);
+       }
+       printhex(cookie, 20);
+       printf("TC S1: PASSED\n\n");
+       sleep(1);
+
+       printf("TC S2: security_server_get_gid(): normal case. trying to get GID of \"tel_gprs\" \n");
+       ret = security_server_get_gid("tel_gprs");
+       if(ret < 0)
+       {
+               printf("Test failed: %d\n", ret);
+               exit(-1);
+       }
+       printf("TC S2: PASSED with gid %d\n\n", ret);
+       sleep(1);
+
+       printf("TC S3: security_server_get_gid(): empty object name\n");
+       ret = security_server_get_gid("");
+       if(ret != SECURITY_SERVER_API_ERROR_INPUT_PARAM)
+       {
+               printf("Test failed: %d\n", ret);
+               exit(-1);
+       }
+       printf("TC S3: PASSED\n\n");
+       sleep(1);
+
+       printf("TC S4: security_server_get_gid(): wrong object name. \"teltel\"\n");
+       ret = security_server_get_gid("teltel");
+       if(ret != SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT)
+       {
+               printf("Test failed: %d\n", ret);
+               exit(-1);
+       }
+       printf("TC S4: PASSED\n\n");
+       sleep(1);
+
+       printf("TC S5: security_server_get_object_name(): normal case. trying 6001\n");
+       ret = security_server_get_object_name(6001, obj_name, sizeof(obj_name));
+       if(ret != SECURITY_SERVER_API_SUCCESS)
+       {
+               printf("Test failed: %d\n", ret);
+               exit(-1);
+       }
+       printf("Result: %s\n", obj_name);
+       printf("TC S5: PASSED\n\n");
+       sleep(1);
+
+       printf("TC S6: security_server_get_object_name(): Too small buffer size\n");
+       ret = security_server_get_object_name(6001, obj_name, 5);
+       if(ret != SECURITY_SERVER_API_ERROR_BUFFER_TOO_SMALL)
+       {
+               printf("Test failed: %d\n", ret);
+               exit(-1);
+       }
+       printf("TC S6: PASSED\n\n");
+       sleep(1);
+
+       printf("TC S7: security_server_get_object_name(): Invalid gid\n");
+       ret = security_server_get_object_name(9876, obj_name, sizeof(obj_name));
+       if(ret != SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT)
+       {
+               printf("Test failed: %d\n", ret);
+               exit(-1);
+       }
+       printf("TC S7: PASSED\n\n");
+       sleep(1);
+
+       printf("TC S8: Ask for priviege with default cookie. Normal case to check \"audio\" privilege \n");
+       ret = security_server_get_gid("audio");
+       ret = security_server_check_privilege(cookie, ret);
+       if(ret != SECURITY_SERVER_API_SUCCESS)
+       {
+               printf("Test failed: %d\n", ret);
+               exit(-1);
+       }
+       printf("TC S8: PASSED\n\n");
+       sleep(1);
+
+       printf("TC S9: Ask for priviege with default cookie. with wrong cookie \n");
+       ret = security_server_get_gid("audio");
+       srand(time(NULL));
+       for(i=0;i<20;i++)
+               wrong_cookie[i] = rand() % 255;
+
+       ret = security_server_check_privilege(wrong_cookie, ret);
+       if(ret != SECURITY_SERVER_API_ERROR_ACCESS_DENIED)
+       {
+               printf("Test failed: %d\n", ret);
+               exit(-1);
+       }
+       printf("TC S9: PASSED\n\n");
+       sleep(1);
+
+       printf("TC S10: Close socket just after sending request msg. This is done not by library call with simulating security_server_get_gid() API \n");
+       ret = fake_get_gid("audio");
+       printf("TC S10: Watch whether security server has crhashed or not.\n\n");
+       sleep(1);
+
+       printf("TC S11: get PID of a given cookie --> default cookie case \n");
+       ret = security_server_get_cookie_pid(cookie);
+       if(ret != 0)
+       {
+               printf("Test failed: %d\n", ret);
+               exit(-1);
+       }
+       printf("TC S11: PASSED\n\n");
+       sleep(1);
+
+       printf("TC S12: get PID of a given cookie --> non existing cookie \n");
+       ret = security_server_get_cookie_pid(wrong_cookie);
+       if(ret != SECURITY_SERVER_API_ERROR_NO_SUCH_COOKIE)
+       {
+               printf("Test failed: %d\n", ret);
+               exit(-1);
+       }
+       printf("TC S12: PASSED\n\n");
+       sleep(1);
+
+       printf("TC S13: get PID of a given cookie --> NULL cookie \n");
+       ret = security_server_get_cookie_pid(NULL);
+       if(ret != SECURITY_SERVER_API_ERROR_INPUT_PARAM)
+       {
+               printf("Test failed: %d\n", ret);
+               exit(-1);
+       }
+       printf("TC S13: PASSED\n\n");
+       sleep(1);
+
+       printf("TC S14: Communicating with client and test cookie and privilege control \n");
+       printf("\tWaiting for client...\n");
+       server_sockfd = create_new_socket();
+       if(server_sockfd < 1)
+       {
+               printf("Error on creating a new socket\n");
+               printf("Test failed: %d\n", ret);
+               exit(1);
+       }
+
+       if(listen(server_sockfd, 5) < 0)
+       {
+               printf("%s\n", "listen() failed. exiting...");
+               printf("Test failed: %d\n", ret);
+               goto error;
+       }
+
+       while(1)
+       {       
+               accept_poll[0].fd = server_sockfd;
+               accept_poll[0].events = POLLIN;
+               ret = poll(accept_poll, 1, 5000);
+
+               /* Call poll() to wait for socket connection */
+               ret = poll(accept_poll, 1, 5000);
+               if(ret < 0)
+               {
+                       printf("%s\n", "poll() error");
+                       printf("Test failed: %d\n", ret);
+                       goto error;
+               }
+               if(ret == 0)
+               {
+                       continue;
+               }
+
+               errno = 0;
+               client_len = sizeof(clientaddr);
+               client_sockfd = accept(server_sockfd,
+                               (struct sockaddr *)&clientaddr,
+                               &client_len);
+               if(client_sockfd < 0)
+               {
+                       printf("Cannot accept client. errno=%d\n", errno);
+                       printf("Test failed: %d\n", ret);
+                       goto error;
+               }
+
+               printf("New session accepted\n");
+
+               /* Wait until packet received */
+               client_poll[0].fd = client_sockfd;
+               client_poll[0].events = POLLIN;
+
+               /* Poll here */
+               ret = poll(client_poll, 1, 500);
+               if(ret < 0)
+               {
+                       printf("%s\n", "poll() error");
+                       printf("Test failed: %d\n", ret);
+                       goto error;
+               }
+               if(ret == 0)
+               {
+                       close(client_sockfd);
+                       client_sockfd = 0;
+                       printf("%s\n", "No request from client. closing socket");
+                       continue;
+               }
+
+               ret = read(client_sockfd, recvbuf, 4);
+               if(recvbuf[0] == 0 && recvbuf[1] == 0 && recvbuf[2] == 0 && recvbuf[3] == 0)
+               {
+                       ret = read(client_sockfd, recvbuf, 24);
+                       if(ret < 24)
+                       {
+                               close(client_sockfd);
+                               printf("cannot read request:%d\n", ret);
+                               close(client_sockfd);
+                               continue;
+                       }
+
+                       memcpy(recved_cookie, recvbuf, 20);
+                       memcpy(&recved_gid, recvbuf+20, sizeof(int));
+
+                       printf("requested cookie: \n");
+                       printhex(recved_cookie, 20);
+                       printf("requested gid: %d\n", recved_gid);
+
+                       ret = security_server_check_privilege(recved_cookie, recved_gid);
+                       if(ret != SECURITY_SERVER_API_SUCCESS && ret != SECURITY_SERVER_API_ERROR_ACCESS_DENIED)
+                       {
+                               printf("Unexpected error occurred: %d\n");
+                               printf("Test failed: %d\n", ret);
+                               goto error;
+                       }
+
+                       printf("Privilege for the request: %d\n", ret);
+
+                       ret = write(client_sockfd, &ret, sizeof(int));
+                       if(ret < sizeof(int))
+                       {
+                               printf("Send error: %d\n", ret);
+                               printf("Test failed: %d\n", ret);
+                               goto error;
+                       }
+
+                       ret = security_server_get_cookie_pid(recved_cookie);
+                       {
+                               if(ret < 0)
+                               {
+                                       printf("Unexpected error occurred: %d\n", ret);
+                                       printf("Test failed: %d\n", ret);
+                                       goto error;
+                               }
+                               if(ret == 0)
+                               {
+                                       printf("client is root process\n");
+                               }
+                               else
+                               {
+                                       printf("Peer PID is %d\n", ret);
+                               }
+                       }
+               }
+               else
+               {
+                       if(recvbuf[0] == 255 && recvbuf[1] == 255 && recvbuf[2] == 255 && recvbuf[3] == 255)
+                       {
+                               char *myargv[5] = {NULL};
+                               int i, cnt;
+                               ret = read(client_sockfd, recvbuf, 28);
+                               if(ret < 28)
+                               {
+                                       close(client_sockfd);
+                                       printf("cannot read request:%d\n", ret);
+                                       close(client_sockfd);
+                                       continue;
+                               }
+
+                               memcpy(recved_cookie, recvbuf, 20);
+                               memcpy(&recved_gid, recvbuf + 20, sizeof(int));
+                               memcpy(&cnt, recvbuf + 24, sizeof(int));
+
+                               if(fork() == 0)
+                               {
+                                       myargv[0] = malloc(strlen("/opt/home/root/security_server_tc_pid_reuser") + 1);
+                                       sprintf(myargv[0], "/opt/home/root/security_server_tc_pid_reuser");
+                                       myargv[1] = malloc(6);
+                                       sprintf(myargv[1], "%d", cnt);
+                                       myargv[2] = malloc(6);
+                                       sprintf(myargv[2], "%d", recved_gid);
+                                       myargv[3] = malloc(40);
+                                       myargv[4] = NULL;
+                                       for(i=0, cnt=0;i<20;i++)
+                                       {
+                                               if(recved_cookie[i] < 0x10)
+                                                       sprintf(myargv[3] + cnt, "0%x", recved_cookie[i]);
+                                               else
+                                                       sprintf(myargv[3] + cnt, "%x", recved_cookie[i]);
+                                               cnt += 2;
+                                       }
+                                       printf("argv[0]=%s, argv[1]=%s, argv[2]=%s, argv[3]=%s\n", myargv[0], myargv[1], myargv[2], myargv[3]);
+                                       ret = execve("/opt/home/root/security_server_tc_pid_reuser", myargv, NULL);
+                                       printf("execve failed. errno=%d\n", errno);
+
+                                       if(myargv[0] != NULL)
+                                               free(myargv[0]);
+                                       if(myargv[1] != NULL)
+                                               free(myargv[1]);
+                                       if(myargv[2] != NULL)
+                                               free(myargv[2]);
+                                       if(myargv[3] != NULL)
+                                               free(myargv[3]);
+                               }
+                       }
+                       else
+                       {
+                               printf("malformed request. %d, %d, %d, %d\n", recvbuf[0], recvbuf[1], recvbuf[2], recvbuf[3]);
+                               printf("Test failed: %d\n", ret);
+                               goto error;
+                       }
+               }
+               if(client_sockfd > 0)
+               {
+                       close(client_sockfd);
+               }
+       }
+error:
+       if(server_sockfd > 0)
+               close(server_sockfd);
+       if(client_sockfd > 0)
+               close(client_sockfd);
+}
diff --git a/testcases/test.h b/testcases/test.h
new file mode 100644 (file)
index 0000000..4202966
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+
+#define SECURITY_SERVER_TEST_SOCK_PATH "/tmp/.security-server-test"