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 65fd1ed..b2f30c2 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 465b5e6..29bfcd8 100644 (file)
@@ -38,5 +38,6 @@ libtlm_common_la_CFLAGS = \
 
 libtlm_common_la_LIBADD = \
        $(TLM_LIBS) \
+       -lpam \
        $(NULL)
 
index 7bac948..9e05290 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 1a81709..7ddc22a 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 488877d..1e4234c 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 01d6ed6..1d40fc5 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);