X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flogin%2Fpam-module.c;h=f469244118cb64a76eff3d2b06546281870c2da4;hb=9588bc32096fc8342bfd8b989689717186d7d86e;hp=49296b5d63ab317b648f0beb3e3d778cf7f62a3c;hpb=5c390a4ae0d383b2003074ed011d47876c7e630c;p=elogind.git diff --git a/src/login/pam-module.c b/src/login/pam-module.c index 49296b5d6..f46924411 100644 --- a/src/login/pam-module.c +++ b/src/login/pam-module.c @@ -36,7 +36,7 @@ #include "audit.h" #include "macro.h" #include "strv.h" -#include "dbus-common.h" +#include "bus-util.h" #include "def.h" #include "socket-util.h" #include "fileio.h" @@ -51,30 +51,26 @@ static int parse_argv(pam_handle_t *handle, assert(argc >= 0); assert(argc == 0 || argv); - for (i = 0; i < (unsigned) argc; i++) { - int k; - + for (i = 0; i < (unsigned) argc; i++) if (startswith(argv[i], "class=")) { - if (class) *class = argv[i] + 6; - } else if (startswith(argv[i], "debug=")) { - k = parse_boolean(argv[i] + 6); + } else if (streq(argv[i], "debug")) { + if (debug) + *debug = true; - if (k < 0) { - pam_syslog(handle, LOG_ERR, "Failed to parse debug= argument."); - return k; - } + } else if (startswith(argv[i], "debug=")) { + int k; - if (debug) + k = parse_boolean(argv[i] + 6); + if (k < 0) + pam_syslog(handle, LOG_WARNING, "Failed to parse debug= argument, ignoring."); + else if (debug) *debug = k; - } else { + } else pam_syslog(handle, LOG_WARNING, "Unknown parameter '%s', ignoring", argv[i]); - return 0; - } - } return 0; } @@ -182,24 +178,26 @@ _public_ PAM_EXTERN int pam_sm_open_session( int flags, int argc, const char **argv) { + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + const char + *username, *id, *object_path, *runtime_path, + *service = NULL, + *tty = NULL, *display = NULL, + *remote_user = NULL, *remote_host = NULL, + *seat = NULL, + *type = NULL, *class = NULL, + *class_pam = NULL, *cvtnr = NULL; + _cleanup_bus_unref_ sd_bus *bus = NULL; + int session_fd = -1, existing, r; + uint32_t uid, pid, vtnr = 0; + bool debug = false, remote; struct passwd *pw; - bool debug = false; - const char *username, *id, *object_path, *runtime_path, *service = NULL, *tty = NULL, *display = NULL, *remote_user = NULL, *remote_host = NULL, *seat = NULL, *type = NULL, *class = NULL, *class_pam = NULL, *cvtnr = NULL; - DBusError error; - uint32_t uid, pid; - DBusMessageIter iter; - int session_fd = -1; - DBusConnection *bus = NULL; - DBusMessage *m = NULL, *reply = NULL; - dbus_bool_t remote, existing; - int r; - uint32_t vtnr = 0; assert(handle); - dbus_error_init(&error); - - /* pam_syslog(handle, LOG_INFO, "pam-systemd initializing"); */ + if (debug) + pam_syslog(handle, LOG_INFO, "pam-systemd initializing"); /* Make this a NOP on non-logind systems */ if (!logind_running()) @@ -208,14 +206,14 @@ _public_ PAM_EXTERN int pam_sm_open_session( if (parse_argv(handle, argc, argv, &class_pam, - &debug) < 0) { - r = PAM_SESSION_ERR; - goto finish; - } + &debug) < 0) + return PAM_SESSION_ERR; r = get_user_data(handle, &username, &pw); - if (r != PAM_SUCCESS) - goto finish; + if (r != PAM_SUCCESS) { + pam_syslog(handle, LOG_ERR, "Failed to get user data."); + return r; + } /* Make sure we don't enter a loop by talking to * systemd-logind when it is actually waiting for the @@ -225,57 +223,29 @@ _public_ PAM_EXTERN int pam_sm_open_session( pam_get_item(handle, PAM_SERVICE, (const void**) &service); if (streq_ptr(service, "systemd-user")) { - char *p, *rt = NULL; + _cleanup_free_ char *p = NULL, *rt = NULL; - if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) pw->pw_uid) < 0) { - r = PAM_BUF_ERR; - goto finish; - } + if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) pw->pw_uid) < 0) + return PAM_BUF_ERR; r = parse_env_file(p, NEWLINE, "RUNTIME", &rt, NULL); - free(p); - - if (r < 0 && r != -ENOENT) { - r = PAM_SESSION_ERR; - free(rt); - goto finish; - } + if (r < 0 && r != -ENOENT) + return PAM_SESSION_ERR; if (rt) { r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0); - free(rt); - if (r != PAM_SUCCESS) { pam_syslog(handle, LOG_ERR, "Failed to set runtime dir."); - goto finish; + return r; } } - r = PAM_SUCCESS; - goto finish; - } - - dbus_connection_set_change_sigpipe(FALSE); - - bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error); - if (!bus) { - pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", bus_error_message(&error)); - r = PAM_SESSION_ERR; - goto finish; + return PAM_SUCCESS; } - m = dbus_message_new_method_call( - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "CreateSession"); - if (!m) { - pam_syslog(handle, LOG_ERR, "Could not allocate create session message."); - r = PAM_BUF_ERR; - goto finish; - } + /* Otherwise, we ask logind to create a session for us */ uid = pw->pw_uid; pid = getpid(); @@ -350,51 +320,61 @@ _public_ PAM_EXTERN int pam_sm_open_session( !streq(remote_host, "localhost") && !streq(remote_host, "localhost.localdomain"); - if (!dbus_message_append_args(m, - DBUS_TYPE_UINT32, &uid, - DBUS_TYPE_UINT32, &pid, - DBUS_TYPE_STRING, &service, - DBUS_TYPE_STRING, &type, - DBUS_TYPE_STRING, &class, - DBUS_TYPE_STRING, &seat, - DBUS_TYPE_UINT32, &vtnr, - DBUS_TYPE_STRING, &tty, - DBUS_TYPE_STRING, &display, - DBUS_TYPE_BOOLEAN, &remote, - DBUS_TYPE_STRING, &remote_user, - DBUS_TYPE_STRING, &remote_host, - DBUS_TYPE_INVALID)) { - pam_syslog(handle, LOG_ERR, "Could not attach parameters to message."); - r = PAM_BUF_ERR; - goto finish; - } + /* Talk to logind over the message bus */ - dbus_message_iter_init_append(m, &iter); + r = sd_bus_open_system(&bus); + if (r < 0) { + pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", strerror(-r)); + return PAM_SESSION_ERR; + } if (debug) pam_syslog(handle, LOG_DEBUG, "Asking logind to create session: " "uid=%u pid=%u service=%s type=%s class=%s seat=%s vtnr=%u tty=%s display=%s remote=%s remote_user=%s remote_host=%s", uid, pid, service, type, class, seat, vtnr, tty, display, yes_no(remote), remote_user, remote_host); - reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error); - if (!reply) { - pam_syslog(handle, LOG_ERR, "Failed to create session: %s", bus_error_message(&error)); - r = PAM_SESSION_ERR; - goto finish; + r = sd_bus_call_method(bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "CreateSession", + &error, + &reply, + "uussssussbssa(sv)", + uid, + pid, + service, + type, + class, + seat, + vtnr, + tty, + display, + remote, + remote_user, + remote_host, + 0); + if (r < 0) { + pam_syslog(handle, LOG_ERR, "Failed to communicate with systemd-logind: %s", strerror(-r)); + if (error.name || error.message) + pam_syslog(handle, LOG_ERR, "systemd-logind returned %s: %s", + error.name ?: "unknown error", + error.message ?: "no message"); + return PAM_SYSTEM_ERR; } - if (!dbus_message_get_args(reply, &error, - DBUS_TYPE_STRING, &id, - DBUS_TYPE_OBJECT_PATH, &object_path, - DBUS_TYPE_STRING, &runtime_path, - DBUS_TYPE_UNIX_FD, &session_fd, - DBUS_TYPE_STRING, &seat, - DBUS_TYPE_UINT32, &vtnr, - DBUS_TYPE_BOOLEAN, &existing, - DBUS_TYPE_INVALID)) { - pam_syslog(handle, LOG_ERR, "Failed to parse message: %s", bus_error_message(&error)); - r = PAM_SESSION_ERR; - goto finish; + r = sd_bus_message_read(reply, + "soshsub", + &id, + &object_path, + &runtime_path, + &session_fd, + &seat, + &vtnr, + &existing); + if (r < 0) { + pam_syslog(handle, LOG_ERR, "Failed to parse message: %s", strerror(-r)); + return PAM_SESSION_ERR; } if (debug) @@ -405,32 +385,31 @@ _public_ PAM_EXTERN int pam_sm_open_session( r = pam_misc_setenv(handle, "XDG_SESSION_ID", id, 0); if (r != PAM_SUCCESS) { pam_syslog(handle, LOG_ERR, "Failed to set session id."); - goto finish; + return r; } r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", runtime_path, 0); if (r != PAM_SUCCESS) { pam_syslog(handle, LOG_ERR, "Failed to set runtime dir."); - goto finish; + return r; } if (!isempty(seat)) { r = pam_misc_setenv(handle, "XDG_SEAT", seat, 0); if (r != PAM_SUCCESS) { pam_syslog(handle, LOG_ERR, "Failed to set seat."); - goto finish; + return r; } } if (vtnr > 0) { - char buf[11]; + char buf[DECIMAL_STR_MAX(vtnr)]; snprintf(buf, sizeof(buf), "%u", vtnr); - char_array_0(buf); r = pam_misc_setenv(handle, "XDG_VTNR", buf, 0); if (r != PAM_SUCCESS) { pam_syslog(handle, LOG_ERR, "Failed to set virtual terminal number."); - goto finish; + return r; } } @@ -441,35 +420,21 @@ _public_ PAM_EXTERN int pam_sm_open_session( } if (session_fd >= 0) { + session_fd = dup(session_fd); + if (session_fd < 0) { + pam_syslog(handle, LOG_ERR, "Failed to dup session fd: %m"); + return PAM_SESSION_ERR; + } + r = pam_set_data(handle, "systemd.session-fd", INT_TO_PTR(session_fd+1), NULL); if (r != PAM_SUCCESS) { pam_syslog(handle, LOG_ERR, "Failed to install session fd."); + close_nointr_nofail(session_fd); return r; } } - session_fd = -1; - - r = PAM_SUCCESS; - -finish: - dbus_error_free(&error); - - if (bus) { - dbus_connection_close(bus); - dbus_connection_unref(bus); - } - - if (m) - dbus_message_unref(m); - - if (reply) - dbus_message_unref(reply); - - if (session_fd >= 0) - close_nointr_nofail(session_fd); - - return r; + return PAM_SUCCESS; } _public_ PAM_EXTERN int pam_sm_close_session( @@ -477,17 +442,15 @@ _public_ PAM_EXTERN int pam_sm_close_session( int flags, int argc, const char **argv) { + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_bus_unref_ sd_bus *bus = NULL; const void *p = NULL, *existing = NULL; const char *id; - DBusConnection *bus = NULL; - DBusMessage *m = NULL, *reply = NULL; - DBusError error; int r; assert(handle); - dbus_error_init(&error); - /* Only release session if it wasn't pre-existing when we * tried to create it */ pam_get_data(handle, "systemd.existing", &existing); @@ -500,35 +463,31 @@ _public_ PAM_EXTERN int pam_sm_close_session( * that it doesn't just go and slaughter us * immediately after closing the fd */ - bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error); - if (!bus) { - pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", bus_error_message(&error)); + r = sd_bus_open_system(&bus); + if (r < 0) { + pam_syslog(handle, LOG_ERR, + "Failed to connect to system bus: %s", strerror(-r)); r = PAM_SESSION_ERR; goto finish; } - m = dbus_message_new_method_call( - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "ReleaseSession"); - if (!m) { - pam_syslog(handle, LOG_ERR, "Could not allocate release session message."); - r = PAM_BUF_ERR; - goto finish; - } - - if (!dbus_message_append_args(m, - DBUS_TYPE_STRING, &id, - DBUS_TYPE_INVALID)) { - pam_syslog(handle, LOG_ERR, "Could not attach parameters to message."); - r = PAM_BUF_ERR; - goto finish; - } + r = sd_bus_call_method(bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "ReleaseSession", + &error, + NULL, + "s", + id); + if (r < 0) { + pam_syslog(handle, LOG_ERR, + "Failed to release session: %s", strerror(-r)); + if (error.name || error.message) + pam_syslog(handle, LOG_ERR, "systemd-logind returned %s: %s", + error.name ?: "unknown error", + error.message ?: "no message"); - reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error); - if (!reply) { - pam_syslog(handle, LOG_ERR, "Failed to release session: %s", bus_error_message(&error)); r = PAM_SESSION_ERR; goto finish; } @@ -541,18 +500,5 @@ finish: if (p) close_nointr(PTR_TO_INT(p) - 1); - dbus_error_free(&error); - - if (bus) { - dbus_connection_close(bus); - dbus_connection_unref(bus); - } - - if (m) - dbus_message_unref(m); - - if (reply) - dbus_message_unref(reply); - return r; }