pam_systemd.c revision b80120c4cba7d134b5437a58437a23fdf7ab2084
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/***
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen This file is part of systemd.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Copyright 2010 Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is free software; you can redistribute it and/or modify it
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen under the terms of the GNU Lesser General Public License as published by
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen (at your option) any later version.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is distributed in the hope that it will be useful, but
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Lesser General Public License for more details.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen You should have received a copy of the GNU Lesser General Public License
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen***/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <errno.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <fcntl.h>
0a6f50c0afdfc434b492493bd9efab20cbee8623Thomas Hindoe Paaboel Andersen#include <sys/file.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <pwd.h>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <endian.h>
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <security/pam_modules.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <security/_pam_macros.h>
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering#include <security/pam_modutil.h>
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering#include <security/pam_ext.h>
a5a807e63a50314e190e9166d8a453cd8dd258e3Zbigniew Jędrzejewski-Szmek#include <security/pam_misc.h>
822db23cfa98a9fbc48f41e11caafb6f1017e052Lennart Poettering
3df3e884ae1237ef0d4d23b0e80f4ffda95ac135Ronny Chevalier#include "bus-common-errors.h"
958b66ea16deddd794b3a52643bd44633e165eadLennart Poettering#include "util.h"
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering#include "audit.h"
4ad7f2761da661853dcc29d542efb4727abb1101Nick Owens#include "macro.h"
39d8db043b599a7382f94bfc904d5e108af438bdLennart Poettering#include "strv.h"
39d8db043b599a7382f94bfc904d5e108af438bdLennart Poettering#include "bus-util.h"
39d8db043b599a7382f94bfc904d5e108af438bdLennart Poettering#include "def.h"
5f402ae84bbc08fe8de5682e371b3f66c387da52Daniel Mack#include "socket-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "fileio.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "bus-error.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "formats-util.h"
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen#include "terminal-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "hostname-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int parse_argv(
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_handle_t *handle,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int argc, const char **argv,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char **class,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char **type,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering bool *debug) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen unsigned i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(argc >= 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(argc == 0 || argv);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (i = 0; i < (unsigned) argc; i++) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (startswith(argv[i], "class=")) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (class)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *class = argv[i] + 6;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (startswith(argv[i], "type=")) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (type)
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering *type = argv[i] + 5;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (streq(argv[i], "debug")) {
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering if (debug)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *debug = true;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (startswith(argv[i], "debug=")) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int k;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering k = parse_boolean(argv[i] + 6);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (k < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_syslog(handle, LOG_WARNING, "Failed to parse debug= argument, ignoring.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else if (debug)
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering *debug = k;
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering } else
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering pam_syslog(handle, LOG_WARNING, "Unknown parameter '%s', ignoring", argv[i]);
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering }
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int get_user_data(
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_handle_t *handle,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char **ret_username,
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering struct passwd **ret_pw) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *username = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct passwd *pw = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(handle);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(ret_username);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(ret_pw);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt r = pam_get_user(handle, &username, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r != PAM_SUCCESS) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_syslog(handle, LOG_ERR, "Failed to get user name.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (isempty(username)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_syslog(handle, LOG_ERR, "User name not valid.");
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering return PAM_AUTH_ERR;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pw = pam_modutil_getpwnam(handle, username);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!pw) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_syslog(handle, LOG_ERR, "Failed to get user data.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return PAM_USER_UNKNOWN;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *ret_pw = pw;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *ret_username = username;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return PAM_SUCCESS;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int get_seat_from_display(const char *display, const char **seat, uint32_t *vtnr) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering union sockaddr_union sa = {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering .un.sun_family = AF_UNIX,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering };
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_free_ char *p = NULL, *tty = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_close_ int fd = -1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct ucred ucred;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int v, r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(display);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(vtnr);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen /* We deduce the X11 socket from the display name, then use
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * SO_PEERCRED to determine the X11 server process, ask for
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen * the controlling tty of that and if it's a VC then we know
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * the seat and the virtual terminal. Sounds ugly, is only
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * semi-ugly. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = socket_from_display(display, &p);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering strncpy(sa.un.sun_path, p, sizeof(sa.un.sun_path)-1);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen if (fd < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = getpeercred(fd, &ucred);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = get_ctty(ucred.pid, NULL, &tty);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering v = vtnr_from_tty(tty);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (v < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return v;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else if (v == 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOENT;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (seat)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *seat = "seat0";
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *vtnr = (uint32_t) v;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int export_legacy_dbus_address(
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_handle_t *handle,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering uid_t uid,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *runtime) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_free_ char *s = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* skip export if kdbus is not active */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!is_kdbus_available())
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return PAM_SUCCESS;
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (asprintf(&s, KERNEL_USER_BUS_ADDRESS_FMT ";" UNIX_USER_BUS_ADDRESS_FMT, uid, runtime) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_syslog(handle, LOG_ERR, "Failed to set bus variable.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return PAM_BUF_ERR;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen r = pam_misc_setenv(handle, "DBUS_SESSION_BUS_ADDRESS", s, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r != PAM_SUCCESS) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_syslog(handle, LOG_ERR, "Failed to set bus variable.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
cc98b3025eeb89addb76a27390cb2baca4eab8b9Torstein Husebø
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return PAM_SUCCESS;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering_public_ PAM_EXTERN int pam_sm_open_session(
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen pam_handle_t *handle,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int flags,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int argc, const char **argv) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *username, *id, *object_path, *runtime_path,
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen *service = NULL,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *tty = NULL, *display = NULL,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *remote_user = NULL, *remote_host = NULL,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *seat = NULL,
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen *type = NULL, *class = NULL,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *class_pam = NULL, *type_pam = NULL, *cvtnr = NULL, *desktop = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen int session_fd = -1, existing, r;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen bool debug = false, remote;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct passwd *pw;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering uint32_t vtnr = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering uid_t original_uid;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(handle);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Make this a NOP on non-logind systems */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!logind_running())
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return PAM_SUCCESS;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (parse_argv(handle,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering argc, argv,
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen &class_pam,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering &type_pam,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering &debug) < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return PAM_SESSION_ERR;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (debug)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_syslog(handle, LOG_DEBUG, "pam-systemd initializing");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = get_user_data(handle, &username, &pw);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r != PAM_SUCCESS) {
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen pam_syslog(handle, LOG_ERR, "Failed to get user data.");
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Make sure we don't enter a loop by talking to
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * systemd-logind when it is actually waiting for the
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * background to finish start-up. If the service is
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * "systemd-user" we simply set XDG_RUNTIME_DIR and
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen * leave. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_get_item(handle, PAM_SERVICE, (const void**) &service);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (streq_ptr(service, "systemd-user")) {
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen _cleanup_free_ char *p = NULL, *rt = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (asprintf(&p, "/run/systemd/users/"UID_FMT, pw->pw_uid) < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return PAM_BUF_ERR;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = parse_env_file(p, NEWLINE,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "RUNTIME", &rt,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0 && r != -ENOENT)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return PAM_SESSION_ERR;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (rt) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r != PAM_SUCCESS) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_syslog(handle, LOG_ERR, "Failed to set runtime dir.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = export_legacy_dbus_address(handle, pw->pw_uid, rt);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r != PAM_SUCCESS)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return PAM_SUCCESS;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt /* Otherwise, we ask logind to create a session for us */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_get_item(handle, PAM_XDISPLAY, (const void**) &display);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_get_item(handle, PAM_TTY, (const void**) &tty);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_get_item(handle, PAM_RUSER, (const void**) &remote_user);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt pam_get_item(handle, PAM_RHOST, (const void**) &remote_host);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering seat = pam_getenv(handle, "XDG_SEAT");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (isempty(seat))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering seat = getenv("XDG_SEAT");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering cvtnr = pam_getenv(handle, "XDG_VTNR");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (isempty(cvtnr))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering cvtnr = getenv("XDG_VTNR");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
0014a4ad505d119c7ac4346d9d774c3f17f663a5Lennart Poettering type = pam_getenv(handle, "XDG_SESSION_TYPE");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (isempty(type))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering type = getenv("XDG_SESSION_TYPE");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (isempty(type))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering type = type_pam;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering class = pam_getenv(handle, "XDG_SESSION_CLASS");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (isempty(class))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering class = getenv("XDG_SESSION_CLASS");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (isempty(class))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering class = class_pam;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering desktop = pam_getenv(handle, "XDG_SESSION_DESKTOP");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (isempty(desktop))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering desktop = getenv("XDG_SESSION_DESKTOP");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering tty = strempty(tty);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (strchr(tty, ':')) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering /* A tty with a colon is usually an X11 display,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering * placed there to show up in utmp. We rearrange
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering * things and don't pretend that an X display was a
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering * tty. */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (isempty(display))
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering display = tty;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering tty = NULL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering } else if (streq(tty, "cron")) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering /* cron has been setting PAM_TTY to "cron" for a very
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering * long time and it probably shouldn't stop doing that
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering * for compatibility reasons. */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering type = "unspecified";
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering class = "background";
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering tty = NULL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering } else if (streq(tty, "ssh")) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering /* ssh has been setting PAM_TTY to "ssh" for a very
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering * long time and probably shouldn't stop doing that
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering * for compatibility reasons. */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering type ="tty";
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering class = "user";
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering tty = NULL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering /* If this fails vtnr will be 0, that's intended */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (!isempty(cvtnr))
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering (void) safe_atou32(cvtnr, &vtnr);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (!isempty(display) && !vtnr) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (isempty(seat))
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering get_seat_from_display(display, &seat, &vtnr);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering else if (streq(seat, "seat0"))
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering get_seat_from_display(display, NULL, &vtnr);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (seat && !streq(seat, "seat0") && vtnr != 0) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering pam_syslog(handle, LOG_DEBUG, "Ignoring vtnr %"PRIu32" for %s which is not seat0", vtnr, seat);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering vtnr = 0;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (isempty(type))
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering type = !isempty(display) ? "x11" :
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering !isempty(tty) ? "tty" : "unspecified";
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (isempty(class))
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering class = streq(type, "unspecified") ? "background" : "user";
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering remote = !isempty(remote_host) && !is_localhost(remote_host);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering /* Talk to logind over the message bus */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = sd_bus_open_system(&bus);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", strerror(-r));
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return PAM_SESSION_ERR;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (debug)
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt pam_syslog(handle, LOG_DEBUG, "Asking logind to create session: "
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering "uid="UID_FMT" pid="PID_FMT" service=%s type=%s class=%s desktop=%s seat=%s vtnr=%"PRIu32" tty=%s display=%s remote=%s remote_user=%s remote_host=%s",
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering pw->pw_uid, getpid(),
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering strempty(service),
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering type, class, strempty(desktop),
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering strempty(seat), vtnr, strempty(tty), strempty(display),
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering yes_no(remote), strempty(remote_user), strempty(remote_host));
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = sd_bus_call_method(bus,
8d3d7072e609ef0e0fb37e1d19a29307d58146c3Michal Schmidt "org.freedesktop.login1",
8d3d7072e609ef0e0fb37e1d19a29307d58146c3Michal Schmidt "/org/freedesktop/login1",
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering "org.freedesktop.login1.Manager",
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering "CreateSession",
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering &error,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering &reply,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering "uusssssussbssa(sv)",
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering (uint32_t) pw->pw_uid,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering (uint32_t) getpid(),
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering service,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering type,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering class,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering desktop,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering seat,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering vtnr,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering tty,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen display,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering remote,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen remote_user,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen remote_host,
c92e531c82a9815ec349aa1bf31236b86b2d5311Lennart Poettering 0);
c92e531c82a9815ec349aa1bf31236b86b2d5311Lennart Poettering if (r < 0) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (sd_bus_error_has_name(&error, BUS_ERROR_SESSION_BUSY)) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen pam_syslog(handle, LOG_DEBUG, "Cannot create session: %s", bus_error_message(&error, r));
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return PAM_SUCCESS;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen } else {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_syslog(handle, LOG_ERR, "Failed to create session: %s", bus_error_message(&error, r));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return PAM_SYSTEM_ERR;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering r = sd_bus_message_read(reply,
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering "soshusub",
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen &id,
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering &object_path,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen &runtime_path,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen &session_fd,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen &original_uid,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen &seat,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen &vtnr,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen &existing);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen pam_syslog(handle, LOG_ERR, "Failed to parse message: %s", strerror(-r));
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return PAM_SESSION_ERR;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (debug)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering pam_syslog(handle, LOG_DEBUG, "Reply from logind: "
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering "id=%s object_path=%s runtime_path=%s session_fd=%d seat=%s vtnr=%u original_uid=%u",
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering id, object_path, runtime_path, session_fd, seat, vtnr, original_uid);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = pam_misc_setenv(handle, "XDG_SESSION_ID", id, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r != PAM_SUCCESS) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_syslog(handle, LOG_ERR, "Failed to set session id.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (original_uid == pw->pw_uid) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Don't set $XDG_RUNTIME_DIR if the user we now
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * authenticated for does not match the original user
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * of the session. We do this in order not to result
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * in privileged apps clobbering the runtime directory
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * unnecessarily. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", runtime_path, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r != PAM_SUCCESS) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_syslog(handle, LOG_ERR, "Failed to set runtime dir.");
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = export_legacy_dbus_address(handle, pw->pw_uid, runtime_path);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r != PAM_SUCCESS)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return r;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering }
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering if (!isempty(seat)) {
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering r = pam_misc_setenv(handle, "XDG_SEAT", seat, 0);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering if (r != PAM_SUCCESS) {
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering pam_syslog(handle, LOG_ERR, "Failed to set seat.");
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering return r;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering }
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering }
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering if (vtnr > 0) {
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering char buf[DECIMAL_STR_MAX(vtnr)];
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sprintf(buf, "%u", vtnr);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = pam_misc_setenv(handle, "XDG_VTNR", buf, 0);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r != PAM_SUCCESS) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_syslog(handle, LOG_ERR, "Failed to set virtual terminal number.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering r = pam_set_data(handle, "systemd.existing", INT_TO_PTR(!!existing), NULL);
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering if (r != PAM_SUCCESS) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_syslog(handle, LOG_ERR, "Failed to install existing flag.");
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering return r;
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
cab5b05903096e1c9cf5575ccc73f89d15c8db69Lennart Poettering if (session_fd >= 0) {
cab5b05903096e1c9cf5575ccc73f89d15c8db69Lennart Poettering session_fd = fcntl(session_fd, F_DUPFD_CLOEXEC, 3);
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering if (session_fd < 0) {
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering pam_syslog(handle, LOG_ERR, "Failed to dup session fd: %m");
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering return PAM_SESSION_ERR;
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering }
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = pam_set_data(handle, "systemd.session-fd", INT_TO_PTR(session_fd+1), NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r != PAM_SUCCESS) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_syslog(handle, LOG_ERR, "Failed to install session fd.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering safe_close(session_fd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering return PAM_SUCCESS;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen_public_ PAM_EXTERN int pam_sm_close_session(
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pam_handle_t *handle,
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering int flags,
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering int argc, const char **argv) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering const void *existing = NULL;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering const char *id;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering int r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(handle);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen /* Only release session if it wasn't pre-existing when we
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen * tried to create it */
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering pam_get_data(handle, "systemd.existing", &existing);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering id = pam_getenv(handle, "XDG_SESSION_ID");
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (id && !existing) {
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering /* Before we go and close the FIFO we need to tell
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering * logind that this is a clean session shutdown, so
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering * that it doesn't just go and slaughter us
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering * immediately after closing the fd */
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering r = sd_bus_open_system(&bus);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (r < 0) {
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", strerror(-r));
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering return PAM_SESSION_ERR;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering }
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering r = sd_bus_call_method(bus,
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering "org.freedesktop.login1",
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering "/org/freedesktop/login1",
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt "org.freedesktop.login1.Manager",
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering "ReleaseSession",
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering &error,
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering NULL,
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering "s",
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering id);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (r < 0) {
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering pam_syslog(handle, LOG_ERR, "Failed to release session: %s", bus_error_message(&error, r));
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering return PAM_SESSION_ERR;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering }
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering }
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering /* Note that we are knowingly leaking the FIFO fd here. This
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering * way, logind can watch us die. If we closed it here it would
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering * not have any clue when that is completed. Given that one
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering * cannot really have multiple PAM sessions open from the same
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering * process this means we will leak one FD at max. */
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering return PAM_SUCCESS;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering}
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering