#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
_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;
+}