16e69612dSEmmanuel Vadot /*- 26e69612dSEmmanuel Vadot * SPDX-License-Identifier: BSD-2-Clause 36e69612dSEmmanuel Vadot * 46e69612dSEmmanuel Vadot * Copyright (c) 2024 Beckhoff Automation GmbH & Co. KG 56e69612dSEmmanuel Vadot * 66e69612dSEmmanuel Vadot * Redistribution and use in source and binary forms, with or without 76e69612dSEmmanuel Vadot * modification, are permitted provided that the following conditions 86e69612dSEmmanuel Vadot * are met: 96e69612dSEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright 106e69612dSEmmanuel Vadot * notice, this list of conditions and the following disclaimer. 116e69612dSEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright 126e69612dSEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the 136e69612dSEmmanuel Vadot * documentation and/or other materials provided with the distribution. 146e69612dSEmmanuel Vadot * 156e69612dSEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 166e69612dSEmmanuel Vadot * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 176e69612dSEmmanuel Vadot * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 186e69612dSEmmanuel Vadot * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 196e69612dSEmmanuel Vadot * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 206e69612dSEmmanuel Vadot * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 216e69612dSEmmanuel Vadot * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 226e69612dSEmmanuel Vadot * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 236e69612dSEmmanuel Vadot * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 246e69612dSEmmanuel Vadot * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 256e69612dSEmmanuel Vadot * SUCH DAMAGE. 266e69612dSEmmanuel Vadot */ 276e69612dSEmmanuel Vadot 286e69612dSEmmanuel Vadot #include <sys/stat.h> 296e69612dSEmmanuel Vadot #include <dirent.h> 306e69612dSEmmanuel Vadot #include <errno.h> 316e69612dSEmmanuel Vadot #include <fcntl.h> 326e69612dSEmmanuel Vadot #include <stdio.h> 336e69612dSEmmanuel Vadot #include <stdlib.h> 346e69612dSEmmanuel Vadot #include <string.h> 356e69612dSEmmanuel Vadot #include <unistd.h> 366e69612dSEmmanuel Vadot #include <pwd.h> 376e69612dSEmmanuel Vadot 386e69612dSEmmanuel Vadot #define PAM_SM_SESSION 396e69612dSEmmanuel Vadot 406e69612dSEmmanuel Vadot #include <security/pam_appl.h> 416e69612dSEmmanuel Vadot #include <security/pam_modules.h> 426e69612dSEmmanuel Vadot #include <security/pam_mod_misc.h> 436e69612dSEmmanuel Vadot 446e69612dSEmmanuel Vadot #define BASE_RUNTIME_DIR_PREFIX "/var/run/xdg" 456e69612dSEmmanuel Vadot #define RUNTIME_DIR_PREFIX runtime_dir_prefix != NULL ? runtime_dir_prefix : BASE_RUNTIME_DIR_PREFIX 466e69612dSEmmanuel Vadot 476e69612dSEmmanuel Vadot #define RUNTIME_DIR_PREFIX_MODE 0711 486e69612dSEmmanuel Vadot #define RUNTIME_DIR_MODE 0700 /* XDG spec */ 496e69612dSEmmanuel Vadot 506e69612dSEmmanuel Vadot #define XDG_MAX_SESSION 100 /* Arbitrary limit because we need one */ 516e69612dSEmmanuel Vadot 526e69612dSEmmanuel Vadot static int 536e69612dSEmmanuel Vadot _pam_xdg_open(pam_handle_t *pamh, int flags __unused, 546e69612dSEmmanuel Vadot int argc __unused, const char *argv[] __unused) 556e69612dSEmmanuel Vadot { 566e69612dSEmmanuel Vadot struct passwd *passwd; 576e69612dSEmmanuel Vadot const char *user; 586e69612dSEmmanuel Vadot const char *runtime_dir_prefix; 596e69612dSEmmanuel Vadot struct stat sb; 606e69612dSEmmanuel Vadot char *runtime_dir = NULL; 616e69612dSEmmanuel Vadot char *xdg_session_file; 626e69612dSEmmanuel Vadot int rv, rt_dir_prefix, rt_dir, session_file, i; 636e69612dSEmmanuel Vadot 646e69612dSEmmanuel Vadot session_file = -1; 656e69612dSEmmanuel Vadot rt_dir_prefix = -1; 666e69612dSEmmanuel Vadot runtime_dir_prefix = openpam_get_option(pamh, "runtime_dir_prefix"); 676e69612dSEmmanuel Vadot 686e69612dSEmmanuel Vadot /* Get user info */ 696e69612dSEmmanuel Vadot rv = pam_get_item(pamh, PAM_USER, (const void **)&user); 706e69612dSEmmanuel Vadot if (rv != PAM_SUCCESS) { 716e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("Can't get user information"); 726e69612dSEmmanuel Vadot goto out; 736e69612dSEmmanuel Vadot } 746e69612dSEmmanuel Vadot if ((passwd = getpwnam(user)) == NULL) { 756e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("Can't get user information"); 766e69612dSEmmanuel Vadot rv = PAM_SESSION_ERR; 776e69612dSEmmanuel Vadot goto out; 786e69612dSEmmanuel Vadot } 796e69612dSEmmanuel Vadot 806e69612dSEmmanuel Vadot /* Open or create the base xdg directory */ 816e69612dSEmmanuel Vadot rt_dir_prefix = open(RUNTIME_DIR_PREFIX, O_DIRECTORY | O_NOFOLLOW); 826e69612dSEmmanuel Vadot if (rt_dir_prefix < 0) { 836e69612dSEmmanuel Vadot rt_dir_prefix = mkdir(RUNTIME_DIR_PREFIX, RUNTIME_DIR_PREFIX_MODE); 846e69612dSEmmanuel Vadot if (rt_dir_prefix != 0) { 856e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("Can't mkdir %s", RUNTIME_DIR_PREFIX); 866e69612dSEmmanuel Vadot rv = PAM_SESSION_ERR; 876e69612dSEmmanuel Vadot goto out; 886e69612dSEmmanuel Vadot } 896e69612dSEmmanuel Vadot rt_dir_prefix = open(RUNTIME_DIR_PREFIX, O_DIRECTORY | O_NOFOLLOW); 906e69612dSEmmanuel Vadot } 916e69612dSEmmanuel Vadot 926e69612dSEmmanuel Vadot /* Open or create the user xdg directory */ 936e69612dSEmmanuel Vadot rt_dir = openat(rt_dir_prefix, user, O_DIRECTORY | O_NOFOLLOW); 946e69612dSEmmanuel Vadot if (rt_dir < 0) { 956e69612dSEmmanuel Vadot rt_dir = mkdirat(rt_dir_prefix, user, RUNTIME_DIR_MODE); 966e69612dSEmmanuel Vadot if (rt_dir != 0) { 976e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("mkdir: %s/%s (%d)", RUNTIME_DIR_PREFIX, user, rt_dir); 986e69612dSEmmanuel Vadot rv = PAM_SESSION_ERR; 996e69612dSEmmanuel Vadot goto out; 1006e69612dSEmmanuel Vadot } 1016e69612dSEmmanuel Vadot rv = fchownat(rt_dir_prefix, user, passwd->pw_uid, passwd->pw_gid, 0); 1026e69612dSEmmanuel Vadot if (rv != 0) { 1036e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("fchownat: %s/%s (%d)", RUNTIME_DIR_PREFIX, user, rv); 1046e69612dSEmmanuel Vadot rv = unlinkat(rt_dir_prefix, user, AT_REMOVEDIR); 1056e69612dSEmmanuel Vadot if (rv == -1) 1066e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("unlinkat: %s/%s (%d)", RUNTIME_DIR_PREFIX, user, errno); 1076e69612dSEmmanuel Vadot rv = PAM_SESSION_ERR; 1086e69612dSEmmanuel Vadot goto out; 1096e69612dSEmmanuel Vadot } 1106e69612dSEmmanuel Vadot } else { 1116e69612dSEmmanuel Vadot /* Check that the already create dir is correctly owned */ 1126e69612dSEmmanuel Vadot rv = fstatat(rt_dir_prefix, user, &sb, 0); 1136e69612dSEmmanuel Vadot if (rv == -1) { 1146e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("fstatat %s/%s failed (%d)", RUNTIME_DIR_PREFIX, user, errno); 1156e69612dSEmmanuel Vadot rv = PAM_SESSION_ERR; 1166e69612dSEmmanuel Vadot goto out; 1176e69612dSEmmanuel Vadot } 1186e69612dSEmmanuel Vadot if (sb.st_uid != passwd->pw_uid || 1196e69612dSEmmanuel Vadot sb.st_gid != passwd->pw_gid) { 1206e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("%s/%s isn't owned by %d:%d\n", RUNTIME_DIR_PREFIX, user, passwd->pw_uid, passwd->pw_gid); 1216e69612dSEmmanuel Vadot rv = PAM_SESSION_ERR; 1226e69612dSEmmanuel Vadot goto out; 1236e69612dSEmmanuel Vadot } 1246e69612dSEmmanuel Vadot /* Test directory mode */ 1256e69612dSEmmanuel Vadot if ((sb.st_mode & 0x1FF) != RUNTIME_DIR_MODE) { 1266e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("%s/%s have wrong mode\n", RUNTIME_DIR_PREFIX, user); 1276e69612dSEmmanuel Vadot rv = PAM_SESSION_ERR; 1286e69612dSEmmanuel Vadot goto out; 1296e69612dSEmmanuel Vadot } 1306e69612dSEmmanuel Vadot } 1316e69612dSEmmanuel Vadot 1326e69612dSEmmanuel Vadot /* Setup the environment variable */ 1332d2950c8SEmmanuel Vadot rv = asprintf(&runtime_dir, "XDG_RUNTIME_DIR=%s/%s", RUNTIME_DIR_PREFIX, user); 1342d2950c8SEmmanuel Vadot if (rv < 0) { 1352d2950c8SEmmanuel Vadot PAM_VERBOSE_ERROR("asprintf failed %d\n", rv); 1362d2950c8SEmmanuel Vadot rv = PAM_SESSION_ERR; 1372d2950c8SEmmanuel Vadot goto out; 1382d2950c8SEmmanuel Vadot } 1396e69612dSEmmanuel Vadot rv = pam_putenv(pamh, runtime_dir); 1406e69612dSEmmanuel Vadot if (rv != PAM_SUCCESS) { 1416e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("pam_putenv: failed (%d)", rv); 1426e69612dSEmmanuel Vadot rv = PAM_SESSION_ERR; 1436e69612dSEmmanuel Vadot goto out; 1446e69612dSEmmanuel Vadot } 1456e69612dSEmmanuel Vadot 1466e69612dSEmmanuel Vadot /* Setup the session count file */ 1476e69612dSEmmanuel Vadot for (i = 0; i < XDG_MAX_SESSION; i++) { 1482d2950c8SEmmanuel Vadot rv = asprintf(&xdg_session_file, "%s/xdg_session.%d", user, i); 1492d2950c8SEmmanuel Vadot if (rv < 0) { 1502d2950c8SEmmanuel Vadot PAM_VERBOSE_ERROR("asprintf failed %d\n", rv); 1512d2950c8SEmmanuel Vadot rv = PAM_SESSION_ERR; 1522d2950c8SEmmanuel Vadot goto out; 1532d2950c8SEmmanuel Vadot } 154*5acbe6d1SEmmanuel Vadot rv = 0; 1556e69612dSEmmanuel Vadot session_file = openat(rt_dir_prefix, xdg_session_file, O_CREAT | O_EXCL, RUNTIME_DIR_MODE); 1566e69612dSEmmanuel Vadot free(xdg_session_file); 1576e69612dSEmmanuel Vadot if (session_file >= 0) 1586e69612dSEmmanuel Vadot break; 1596e69612dSEmmanuel Vadot } 1606e69612dSEmmanuel Vadot if (session_file < 0) { 1616e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("Too many sessions"); 1626e69612dSEmmanuel Vadot rv = PAM_SESSION_ERR; 1636e69612dSEmmanuel Vadot goto out; 1646e69612dSEmmanuel Vadot } 1656e69612dSEmmanuel Vadot 1666e69612dSEmmanuel Vadot out: 1676e69612dSEmmanuel Vadot if (session_file >= 0) 1686e69612dSEmmanuel Vadot close(session_file); 1696e69612dSEmmanuel Vadot if (rt_dir_prefix >= 0) 1706e69612dSEmmanuel Vadot close(rt_dir_prefix); 1716e69612dSEmmanuel Vadot 1726e69612dSEmmanuel Vadot if (runtime_dir) 1736e69612dSEmmanuel Vadot free(runtime_dir); 1746e69612dSEmmanuel Vadot return (rv); 1756e69612dSEmmanuel Vadot } 1766e69612dSEmmanuel Vadot 1776e69612dSEmmanuel Vadot static int 1786e69612dSEmmanuel Vadot remove_dir(int fd) 1796e69612dSEmmanuel Vadot { 1806e69612dSEmmanuel Vadot DIR *dirp; 1816e69612dSEmmanuel Vadot struct dirent *dp; 1826e69612dSEmmanuel Vadot 1836e69612dSEmmanuel Vadot dirp = fdopendir(fd); 1846e69612dSEmmanuel Vadot if (dirp == NULL) 1856e69612dSEmmanuel Vadot return (-1); 1866e69612dSEmmanuel Vadot 1876e69612dSEmmanuel Vadot while ((dp = readdir(dirp)) != NULL) { 1886e69612dSEmmanuel Vadot if (dp->d_type == DT_DIR) { 1896e69612dSEmmanuel Vadot int dirfd; 1906e69612dSEmmanuel Vadot 1916e69612dSEmmanuel Vadot if (strcmp(dp->d_name, ".") == 0 || 1926e69612dSEmmanuel Vadot strcmp(dp->d_name, "..") == 0) 1936e69612dSEmmanuel Vadot continue; 1946e69612dSEmmanuel Vadot dirfd = openat(fd, dp->d_name, 0); 1956e69612dSEmmanuel Vadot remove_dir(dirfd); 1966e69612dSEmmanuel Vadot close(dirfd); 1976e69612dSEmmanuel Vadot unlinkat(fd, dp->d_name, AT_REMOVEDIR); 1986e69612dSEmmanuel Vadot continue; 1996e69612dSEmmanuel Vadot } 2006e69612dSEmmanuel Vadot unlinkat(fd, dp->d_name, 0); 2016e69612dSEmmanuel Vadot } 2026e69612dSEmmanuel Vadot 2036e69612dSEmmanuel Vadot return (0); 2046e69612dSEmmanuel Vadot } 2056e69612dSEmmanuel Vadot 2066e69612dSEmmanuel Vadot static int 2076e69612dSEmmanuel Vadot _pam_xdg_close(pam_handle_t *pamh __unused, int flags __unused, 2086e69612dSEmmanuel Vadot int argc __unused, const char *argv[] __unused) 2096e69612dSEmmanuel Vadot { 2106e69612dSEmmanuel Vadot struct passwd *passwd; 2116e69612dSEmmanuel Vadot const char *user; 2126e69612dSEmmanuel Vadot const char *runtime_dir_prefix; 2136e69612dSEmmanuel Vadot struct stat sb; 2146e69612dSEmmanuel Vadot char *xdg_session_file; 2156e69612dSEmmanuel Vadot int rv, rt_dir_prefix, rt_dir, session_file, i; 2166e69612dSEmmanuel Vadot 2176e69612dSEmmanuel Vadot rt_dir = -1; 2186e69612dSEmmanuel Vadot rt_dir_prefix = -1; 2196e69612dSEmmanuel Vadot runtime_dir_prefix = openpam_get_option(pamh, "runtime_dir_prefix"); 2206e69612dSEmmanuel Vadot 2216e69612dSEmmanuel Vadot /* Get user info */ 2226e69612dSEmmanuel Vadot rv = pam_get_item(pamh, PAM_USER, (const void **)&user); 2236e69612dSEmmanuel Vadot if (rv != PAM_SUCCESS) { 2246e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("Can't get user information"); 2256e69612dSEmmanuel Vadot goto out; 2266e69612dSEmmanuel Vadot } 2276e69612dSEmmanuel Vadot if ((passwd = getpwnam(user)) == NULL) { 2286e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("Can't get user information"); 2296e69612dSEmmanuel Vadot rv = PAM_SESSION_ERR; 2306e69612dSEmmanuel Vadot goto out; 2316e69612dSEmmanuel Vadot } 2326e69612dSEmmanuel Vadot 2336e69612dSEmmanuel Vadot /* Open the xdg base directory */ 2346e69612dSEmmanuel Vadot rt_dir_prefix = open(RUNTIME_DIR_PREFIX, O_DIRECTORY | O_NOFOLLOW); 2356e69612dSEmmanuel Vadot if (rt_dir_prefix < 0) { 2366e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("open: %s failed (%d)\n", runtime_dir_prefix, rt_dir_prefix); 2376e69612dSEmmanuel Vadot rv = PAM_SESSION_ERR; 2386e69612dSEmmanuel Vadot goto out; 2396e69612dSEmmanuel Vadot } 2406e69612dSEmmanuel Vadot /* Check that the already created dir is correctly owned */ 2416e69612dSEmmanuel Vadot rv = fstatat(rt_dir_prefix, user, &sb, 0); 2426e69612dSEmmanuel Vadot if (rv == -1) { 2436e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("fstatat %s/%s failed (%d)", RUNTIME_DIR_PREFIX, user, errno); 2446e69612dSEmmanuel Vadot rv = PAM_SESSION_ERR; 2456e69612dSEmmanuel Vadot goto out; 2466e69612dSEmmanuel Vadot } 2476e69612dSEmmanuel Vadot if (sb.st_uid != passwd->pw_uid || 2486e69612dSEmmanuel Vadot sb.st_gid != passwd->pw_gid) { 2496e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("%s/%s isn't owned by %d:%d\n", RUNTIME_DIR_PREFIX, user, passwd->pw_uid, passwd->pw_gid); 2506e69612dSEmmanuel Vadot rv = PAM_SESSION_ERR; 2516e69612dSEmmanuel Vadot goto out; 2526e69612dSEmmanuel Vadot } 2536e69612dSEmmanuel Vadot /* Test directory mode */ 2546e69612dSEmmanuel Vadot if ((sb.st_mode & 0x1FF) != RUNTIME_DIR_MODE) { 2556e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("%s/%s have wrong mode\n", RUNTIME_DIR_PREFIX, user); 2566e69612dSEmmanuel Vadot rv = PAM_SESSION_ERR; 2576e69612dSEmmanuel Vadot goto out; 2586e69612dSEmmanuel Vadot } 2596e69612dSEmmanuel Vadot 2606e69612dSEmmanuel Vadot /* Open the user xdg directory */ 2616e69612dSEmmanuel Vadot rt_dir = openat(rt_dir_prefix, user, O_DIRECTORY | O_NOFOLLOW); 2626e69612dSEmmanuel Vadot if (rt_dir < 0) { 2636e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("openat: %s/%s failed (%d)\n", RUNTIME_DIR_PREFIX, user, rt_dir_prefix); 2646e69612dSEmmanuel Vadot rv = PAM_SESSION_ERR; 2656e69612dSEmmanuel Vadot goto out; 2666e69612dSEmmanuel Vadot } 2676e69612dSEmmanuel Vadot 2686e69612dSEmmanuel Vadot /* Get the last session file created */ 2696e69612dSEmmanuel Vadot for (i = XDG_MAX_SESSION; i >= 0; i--) { 2702d2950c8SEmmanuel Vadot rv = asprintf(&xdg_session_file, "%s/xdg_session.%d", user, i); 2712d2950c8SEmmanuel Vadot if (rv < 0) { 2722d2950c8SEmmanuel Vadot PAM_VERBOSE_ERROR("asprintf failed %d\n", rv); 2732d2950c8SEmmanuel Vadot rv = PAM_SESSION_ERR; 2742d2950c8SEmmanuel Vadot goto out; 2752d2950c8SEmmanuel Vadot } 276*5acbe6d1SEmmanuel Vadot rv = 0; 2776e69612dSEmmanuel Vadot session_file = openat(rt_dir_prefix, xdg_session_file, 0); 2786e69612dSEmmanuel Vadot if (session_file >= 0) { 2796e69612dSEmmanuel Vadot unlinkat(rt_dir_prefix, xdg_session_file, 0); 2806e69612dSEmmanuel Vadot free(xdg_session_file); 2816e69612dSEmmanuel Vadot break; 2826e69612dSEmmanuel Vadot } 2836e69612dSEmmanuel Vadot free(xdg_session_file); 2846e69612dSEmmanuel Vadot } 2856e69612dSEmmanuel Vadot if (session_file < 0) { 2866e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("Can't find session number\n"); 2876e69612dSEmmanuel Vadot rv = PAM_SESSION_ERR; 2886e69612dSEmmanuel Vadot goto out; 2896e69612dSEmmanuel Vadot } 2906e69612dSEmmanuel Vadot close(session_file); 2916e69612dSEmmanuel Vadot 2926e69612dSEmmanuel Vadot /* Final cleanup if last user session */ 2936e69612dSEmmanuel Vadot if (i == 0) { 2946e69612dSEmmanuel Vadot remove_dir(rt_dir); 2956e69612dSEmmanuel Vadot if (unlinkat(rt_dir_prefix, user, AT_REMOVEDIR) != 0) { 2966e69612dSEmmanuel Vadot PAM_VERBOSE_ERROR("Can't cleanup %s/%s\n", runtime_dir_prefix, user); 2976e69612dSEmmanuel Vadot rv = PAM_SESSION_ERR; 2986e69612dSEmmanuel Vadot goto out; 2996e69612dSEmmanuel Vadot } 3006e69612dSEmmanuel Vadot } 3016e69612dSEmmanuel Vadot 3026e69612dSEmmanuel Vadot rv = PAM_SUCCESS; 3036e69612dSEmmanuel Vadot out: 3046e69612dSEmmanuel Vadot if (rt_dir >= 0) 3056e69612dSEmmanuel Vadot close(rt_dir); 3066e69612dSEmmanuel Vadot if (rt_dir_prefix >= 0) 3076e69612dSEmmanuel Vadot close(rt_dir_prefix); 3086e69612dSEmmanuel Vadot return (rv); 3096e69612dSEmmanuel Vadot } 3106e69612dSEmmanuel Vadot 3116e69612dSEmmanuel Vadot PAM_EXTERN int 3126e69612dSEmmanuel Vadot pam_sm_open_session(pam_handle_t *pamh, int flags, 3136e69612dSEmmanuel Vadot int argc, const char *argv[]) 3146e69612dSEmmanuel Vadot { 3156e69612dSEmmanuel Vadot 3166e69612dSEmmanuel Vadot return (_pam_xdg_open(pamh, flags, argc, argv)); 3176e69612dSEmmanuel Vadot } 3186e69612dSEmmanuel Vadot 3196e69612dSEmmanuel Vadot PAM_EXTERN int 3206e69612dSEmmanuel Vadot pam_sm_close_session(pam_handle_t *pamh, int flags, 3216e69612dSEmmanuel Vadot int argc, const char *argv[]) 3226e69612dSEmmanuel Vadot { 3236e69612dSEmmanuel Vadot 3246e69612dSEmmanuel Vadot return (_pam_xdg_close(pamh, flags, argc, argv)); 3256e69612dSEmmanuel Vadot } 3266e69612dSEmmanuel Vadot 3276e69612dSEmmanuel Vadot PAM_MODULE_ENTRY("pam_xdg"); 328