fix the closing session bug, even if next user authentication is failed. 86/37386/5
authorSangjung Woo <sangjung.woo@samsung.com>
Wed, 25 Mar 2015 12:27:41 +0000 (21:27 +0900)
committerSangjung Woo <sangjung.woo@samsung.com>
Fri, 10 Apr 2015 05:36:40 +0000 (14:36 +0900)
When switching user by calling switchUser method, current opened session
is closed without verifying the next user authentication (i.e. username
and password). Because of this reason, there could be no remains session
in case of failure of user authentication for next user.

This patch checks the next user authentication and immediately return
FALSE when failed so that current session is not terminated. PAM service
name is specified in /etc/tlm.conf to change easily. (Default system-auth)

Change-Id: I794243faa7ebaf47f53bdf9b9368e14dbf8c509a
Signed-off-by: Sangjung Woo <sangjung.woo@samsung.com>
data/tlm.conf.in
src/common/Makefile.am
src/common/tlm-config-general.h
src/common/tlm-utils.c
src/common/tlm-utils.h
src/daemon/tlm-seat.c

index 65fd1ed1e9dc02f91aca7e6c7c88b32ad30f5ca1..b2f30c21a17f150ff79606aa9219c9b5dfb8165f 100644 (file)
@@ -28,6 +28,9 @@ PAM_SERVICE=tlm-login
 # PAM service file for default user
 DEFAULT_PAM_SERVICE=tlm-default-login
 #
+# PAM authentication service for tizen TV
+PAM_AUTHENTICATION_SERVICE=system-auth
+#
 # Default (guest) username or template to use
 #  %S - seat number
 #  %I - seat id string
index 465b5e667f16635b07a30b333a07aed32774b6a3..29bfcd8abbb011503543966ffa6b80c379d30f0f 100644 (file)
@@ -38,5 +38,6 @@ libtlm_common_la_CFLAGS = \
 
 libtlm_common_la_LIBADD = \
        $(TLM_LIBS) \
+       -lpam \
        $(NULL)
 
index 7bac9486671270efe537699b7063466411e91f3c..9e0529012a5b156a7bcef8ce2491bb367231b168 100644 (file)
  */ 
 #define TLM_CONFIG_GENERAL_PAM_SERVICE      "PAM_SERVICE"
 
+
+#define TLM_CONFIG_PAM_AUTHENTICATION_SERVICE   "PAM_AUTHENTICATION_SERVICE"
+
 /**
  * TLM_CONFIG_GENERAL_DEFAULT_PAM_SERVICE:
  *
index 1a81709ffb502df81d77e66652e945bf6827be74..7ddc22ad1813884171409bd04f3b39622ce79d39 100644 (file)
 #include <unistd.h>
 #include <glib/gstdio.h>
 #include <glib-unix.h>
+#include <security/pam_appl.h>
 #include <errno.h>
 
 #include "tlm-utils.h"
 #include "tlm-log.h"
+#include "tlm-config.h"
+#include "tlm-config-general.h"
 
 #define HOST_NAME_SIZE 256
 
@@ -678,3 +681,97 @@ tlm_utils_watch_for_files (
       _inotify_watcher_cb, w_info, (GDestroyNotify)_watch_info_free);
 }
 
+typedef struct _TlmLoginInfo
+{
+    gchar* username;
+    gchar* password;
+} TlmLoginInfo;
+
+static int func_conv(
+    int num_msg,
+    const struct pam_message **msgs,
+    struct pam_response **resps,
+    void *pdata)
+{
+    int i;
+    const char *login_prompt = "login";
+    const char *pwd_prompt = "Password";
+
+    if (num_msg <= 0)
+        return PAM_CONV_ERR;
+
+    TlmLoginInfo *info = (TlmLoginInfo *)pdata;
+    *resps = g_malloc0 (num_msg * sizeof(struct pam_response));
+
+    for (i=0; i<num_msg; ++i) {
+        struct pam_response *resp = *resps + i;
+
+        if (resp) {
+            if (msgs[i]->msg_style == PAM_PROMPT_ECHO_ON &&
+                strncmp(msgs[i]->msg, login_prompt, strlen(login_prompt)) == 0) {
+                resp->resp = strndup (info->username, PAM_MAX_RESP_SIZE - 1);
+            }
+            else if (msgs[i]->msg_style == PAM_PROMPT_ECHO_OFF &&
+                     strncmp(msgs[i]->msg, pwd_prompt, strlen(pwd_prompt)) == 0) {
+                resp->resp = strndup (info->password, PAM_MAX_RESP_SIZE - 1);
+            }
+            else {
+                resp->resp = NULL;
+            }
+            resp->resp_retcode = PAM_SUCCESS;
+        }
+    }
+    return PAM_SUCCESS;
+}
+
+gboolean
+tlm_authenticate_user (
+    TlmConfig *config,
+    const gchar *username,
+    const gchar *password)
+{
+    pam_handle_t *pam_h = NULL;
+    gboolean ret_auth = FALSE;
+    int ret;
+    const gchar *service = NULL;
+    TlmLoginInfo *info = NULL;
+
+    if (!password || !username) {
+        WARN("username or password would be NULL");
+        return FALSE;
+    }
+
+    // If TLM_CONFIG_PAM_AUTHENTICATION_SERVICE is not specified in tlm.conf
+    // use "system-auth" as defult.
+    service = tlm_config_get_string(config, TLM_CONFIG_GENERAL,
+                                    // TLM_CONFIG_PAM_AUTHENTICATION_SERVICE);
+                                    TLM_CONFIG_GENERAL_PAM_SERVICE);
+    if (!service)
+        service = "system-auth";
+
+    info = g_malloc0 (sizeof (*info));
+    info->username = strndup (username, PAM_MAX_RESP_SIZE - 1);
+    info->password = strndup (password, PAM_MAX_RESP_SIZE - 1);
+    const struct pam_conv conv = {func_conv, info};
+
+    ret = pam_start (service, username, &conv, &pam_h);
+    if (ret != PAM_SUCCESS) {
+        WARN("Failed to pam_start: %d", ret);
+        return FALSE;
+    }
+
+    ret = pam_authenticate (pam_h, PAM_SILENT);
+    if (ret == PAM_SUCCESS)
+        ret_auth = TRUE;
+    else if (ret == PAM_AUTH_ERR)
+        WARN("Failed to get authentication! username: %s", username);
+    else
+        WARN("Failed to pam_authenticate: %d", ret);
+
+    pam_end(pam_h, ret);
+
+    free(info->username);
+    free(info->password);
+    g_free(info);
+    return ret_auth;
+}
index 488877d8b55d07b6664036eba5e22bc267473315..1e4234c49b256079d8f5c94c0795ea634b23530e 100644 (file)
@@ -30,6 +30,8 @@
 #include <sys/types.h>
 #include <glib.h>
 
+#include "tlm-config.h"
+
 G_BEGIN_DECLS
 
 void
@@ -67,6 +69,9 @@ typedef void (*WatchCb) (const gchar *found_item, gboolean is_final, GError *err
 guint
 tlm_utils_watch_for_files (const gchar **watch_list, WatchCb cb, gpointer userdata);
 
+gboolean
+tlm_authenticate_user (TlmConfig *config, const gchar *username, const gchar *password);
+
 G_END_DECLS
 
 #endif /* _TLM_UTILS_H */
index 01d6ed62c3d31a4865e47e0abd5897b0032aa490..1d40fc577322cde8a006b12964ff0525aeda2303 100644 (file)
@@ -457,6 +457,13 @@ tlm_seat_switch_user (TlmSeat *seat,
 
     TlmSeatPrivate *priv = TLM_SEAT_PRIV (seat);
 
+    // If username & its password is not authenticated, immediately return FALSE
+    // so that current session is not terminated.
+    if (!tlm_authenticate_user (priv->config, username, password)) {
+        WARN("fail to tlm_authenticate_user");
+        return FALSE;
+    }
+
     if (!priv->session) {
         return tlm_seat_create_session (seat, service, username, password,
                 environment);