fix the closing session bug, even if next user authentication is failed.
[platform/core/system/tlm.git] / src / common / tlm-utils.c
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;
+}