1From 3f90452cb9d5dbb38906dd161b4dd639be4e45c9 Mon Sep 17 00:00:00 2001 2From: Philipp Zabel <philipp.zabel@gmail.com> 3Date: Sat, 19 Nov 2022 09:52:01 +0100 4Subject: [PATCH 88/92] libweston: Add user authentication support via PAM 5 6Add user authentication support for remote backends via PAM. 7This requires a configuration file /etc/pam.d/weston. 8 9Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com> 10(cherry picked from commit 0733c8f5715a06c1109d380093d4f2e040284140) 11Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 12--- 13 libweston/auth.c | 116 +++++++++++++++++++++++++++++++++ 14 libweston/libweston-internal.h | 5 ++ 15 libweston/meson.build | 13 ++++ 16 meson.build | 2 + 17 pam/meson.build | 8 +++ 18 pam/weston-remote-access | 3 + 19 6 files changed, 147 insertions(+) 20 create mode 100644 libweston/auth.c 21 create mode 100644 pam/meson.build 22 create mode 100644 pam/weston-remote-access 23 24diff --git a/libweston/auth.c b/libweston/auth.c 25new file mode 100644 26index 0000000..2133abb 27--- /dev/null 28+++ b/libweston/auth.c 29@@ -0,0 +1,116 @@ 30+/* 31+ * Copyright © 2022 Philipp Zabel 32+ * 33+ * Permission is hereby granted, free of charge, to any person obtaining 34+ * a copy of this software and associated documentation files (the 35+ * "Software"), to deal in the Software without restriction, including 36+ * without limitation the rights to use, copy, modify, merge, publish, 37+ * distribute, sublicense, and/or sell copies of the Software, and to 38+ * permit persons to whom the Software is furnished to do so, subject to 39+ * the following conditions: 40+ * 41+ * The above copyright notice and this permission notice (including the 42+ * next paragraph) shall be included in all copies or substantial 43+ * portions of the Software. 44+ * 45+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 46+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 47+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 48+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 49+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 50+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 51+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 52+ * SOFTWARE. 53+ */ 54+ 55+#include "config.h" 56+ 57+#include <shared/xalloc.h> 58+#include <stdbool.h> 59+#include "libweston-internal.h" 60+ 61+#ifdef HAVE_PAM 62+ 63+#include <security/pam_appl.h> 64+#include <security/pam_misc.h> 65+ 66+static int 67+weston_pam_conv(int num_msg, const struct pam_message **msg, 68+ struct pam_response **resp, void *appdata_ptr) 69+{ 70+ const char *password = appdata_ptr; 71+ struct pam_response *rsp; 72+ int i; 73+ 74+ if (!num_msg) 75+ return PAM_CONV_ERR; 76+ 77+ rsp = calloc(num_msg, sizeof(*rsp)); 78+ if (!rsp) 79+ return PAM_CONV_ERR; 80+ 81+ for (i = 0; i < num_msg; i++) { 82+ switch (msg[i]->msg_style) { 83+ case PAM_PROMPT_ECHO_OFF: 84+ rsp[i].resp = strdup(password); 85+ break; 86+ case PAM_PROMPT_ECHO_ON: 87+ break; 88+ case PAM_ERROR_MSG: 89+ weston_log("PAM error message: %s\n", msg[i]->msg); 90+ break; 91+ case PAM_TEXT_INFO: 92+ weston_log("PAM info text: %s\n", msg[i]->msg); 93+ break; 94+ default: 95+ free(rsp); 96+ return PAM_CONV_ERR; 97+ } 98+ } 99+ 100+ *resp = rsp; 101+ return PAM_SUCCESS; 102+} 103+ 104+#endif 105+ 106+WL_EXPORT bool 107+weston_authenticate_user(const char *username, const char *password) 108+{ 109+ bool authenticated = false; 110+#ifdef HAVE_PAM 111+ struct pam_conv conv = { 112+ .conv = weston_pam_conv, 113+ .appdata_ptr = strdup(password), 114+ }; 115+ struct pam_handle *pam; 116+ int ret; 117+ 118+ conv.appdata_ptr = strdup(password); 119+ 120+ ret = pam_start("weston-remote-access", username, &conv, &pam); 121+ if (ret != PAM_SUCCESS) { 122+ weston_log("PAM: start failed\n"); 123+ goto out; 124+ } 125+ 126+ ret = pam_authenticate(pam, 0); 127+ if (ret != PAM_SUCCESS) { 128+ weston_log("PAM: authentication failed\n"); 129+ goto out; 130+ } 131+ 132+ ret = pam_acct_mgmt(pam, 0); 133+ if (ret != PAM_SUCCESS) { 134+ weston_log("PAM: account check failed\n"); 135+ goto out; 136+ } 137+ 138+ authenticated = true; 139+out: 140+ ret = pam_end(pam, ret); 141+ assert(ret == PAM_SUCCESS); 142+ free(conv.appdata_ptr); 143+#endif 144+ return authenticated; 145+} 146diff --git a/libweston/libweston-internal.h b/libweston/libweston-internal.h 147index bcfb153..ea5c478 100644 148--- a/libweston/libweston-internal.h 149+++ b/libweston/libweston-internal.h 150@@ -502,4 +502,9 @@ wl_data_device_manager_init(struct wl_display *display); 151 bool 152 weston_output_set_color_outcome(struct weston_output *output); 153 154+/* User authentication for remote backends */ 155+ 156+bool 157+weston_authenticate_user(const char *username, const char *password); 158+ 159 #endif 160diff --git a/libweston/meson.build b/libweston/meson.build 161index 6906244..6f0b624 100644 162--- a/libweston/meson.build 163+++ b/libweston/meson.build 164@@ -10,6 +10,7 @@ deps_libweston = [ 165 srcs_libweston = [ 166 git_version_h, 167 'animation.c', 168+ 'auth.c', 169 'bindings.c', 170 'clipboard.c', 171 'color.c', 172@@ -79,6 +80,18 @@ if dep_egl.found() and dep_gbm.found() 173 deps_libweston += [ dep_egl, dep_gbm ] 174 endif 175 176+if get_option('backend-vnc') 177+ dep_pam = dependency('pam', required: false) 178+ if not dep_pam.found() 179+ dep_pam = cc.find_library('pam') 180+ endif 181+ if not dep_pam.found() 182+ error('VNC backend requires libpam which was not found. Or, you can use \'-Dbackend-vnc=false\'.') 183+ endif 184+ config_h.set('HAVE_PAM', '1') 185+ deps_libweston += dep_pam 186+endif 187+ 188 lib_weston = shared_library( 189 'weston-@0@'.format(libweston_major), 190 srcs_libweston, 191diff --git a/meson.build b/meson.build 192index e03d085..cc510f1 100644 193--- a/meson.build 194+++ b/meson.build 195@@ -44,6 +44,7 @@ dir_data_pc = join_paths(dir_data, 'pkgconfig') 196 dir_lib_pc = join_paths(dir_lib, 'pkgconfig') 197 dir_man = join_paths(dir_prefix, get_option('mandir')) 198 dir_protocol_libweston = join_paths('libweston-@0@'.format(libweston_major), 'protocols') 199+dir_sysconf = join_paths(dir_prefix, get_option('sysconfdir')) 200 201 public_inc = include_directories('include') 202 common_inc = [ include_directories('.'), public_inc ] 203@@ -191,6 +192,7 @@ subdir('wcap') 204 subdir('tests') 205 subdir('data') 206 subdir('man') 207+subdir('pam') 208 209 configure_file(output: 'config.h', configuration: config_h) 210 211diff --git a/pam/meson.build b/pam/meson.build 212new file mode 100644 213index 0000000..7b7eff8 214--- /dev/null 215+++ b/pam/meson.build 216@@ -0,0 +1,8 @@ 217+if not get_option('backend-vnc') 218+ subdir_done() 219+endif 220+ 221+install_data( 222+ 'weston-remote-access', 223+ install_dir: join_paths(dir_sysconf, 'pam.d') 224+) 225diff --git a/pam/weston-remote-access b/pam/weston-remote-access 226new file mode 100644 227index 0000000..d3014dd 228--- /dev/null 229+++ b/pam/weston-remote-access 230@@ -0,0 +1,3 @@ 231+#%PAM-1.0 232+auth include login 233+account include login 234-- 2352.20.1 236 237