pam-module.c revision 75c8e3cffd7da8eede614cf61384957af2c82a29
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <endian.h>
#include <sys/capability.h>
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
#include <security/pam_modutil.h>
#include <security/pam_misc.h>
#include <systemd/sd-daemon.h>
#include "util.h"
#include "macro.h"
#include "strv.h"
#include "dbus-common.h"
#include "def.h"
#include "socket-util.h"
char ***controllers,
char ***reset_controllers,
bool *kill_processes,
char ***kill_only_users,
char ***kill_exclude_users,
bool *debug) {
unsigned i;
for (i = 0; i < (unsigned) argc; i++) {
int k;
return k;
}
if (kill_processes)
*kill_processes = k;
/* As compatibility for old versions */
return k;
}
if (kill_processes)
*kill_processes = k;
if (controllers) {
char **l;
return -ENOMEM;
}
*controllers = l;
}
if (reset_controllers) {
char **l;
return -ENOMEM;
}
*reset_controllers = l;
}
if (kill_only_users) {
char **l;
return -ENOMEM;
}
*kill_only_users = l;
}
if (kill_exclude_users) {
char **l;
return -ENOMEM;
}
*kill_exclude_users = l;
}
return k;
}
if (debug)
*debug = k;
} else {
return -EINVAL;
}
}
return 0;
}
static int get_user_data(
const char **ret_username,
int r;
r = audit_loginuid_from_pid(0, &uid);
if (r >= 0)
else {
if (r != PAM_SUCCESS) {
return r;
}
return PAM_AUTH_ERR;
}
}
if (!pw) {
return PAM_USER_UNKNOWN;
}
return PAM_SUCCESS;
}
static bool check_user_lists(
char **kill_only_users,
char **kill_exclude_users) {
char **l;
if (uid == 0)
else {
if (pw)
}
uid_t u;
if (parse_uid(*l, &u) >= 0)
if (u == uid)
return false;
return false;
}
if (strv_isempty(kill_only_users))
return true;
STRV_FOREACH(l, kill_only_users) {
uid_t u;
if (parse_uid(*l, &u) >= 0)
if (u == uid)
return true;
return true;
}
return false;
}
char *p = NULL;
int r;
int fd;
union sockaddr_union sa;
socklen_t l;
char *tty;
int v;
/* We deduce the X11 socket from the display name, then use
* SO_PEERCRED to determine the X11 server process, ask for
* the controlling tty of that and if it's a VC then we know
* the seat and the virtual terminal. Sounds ugly, is only
* semi-ugly. */
r = socket_from_display(display, &p);
if (r < 0)
return r;
if (fd < 0) {
free(p);
return -errno;
}
free(p);
return -errno;
}
l = sizeof(ucred);
if (r < 0)
return -errno;
if (r < 0)
return r;
v = vtnr_from_tty(tty);
if (v < 0)
return v;
else if (v == 0)
return -ENOENT;
if (seat)
*seat = "seat0";
return 0;
}
int flags,
bool kill_processes = false, 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, *class, *cvtnr = NULL;
char **controllers = NULL, **reset_controllers = NULL, **kill_only_users = NULL, **kill_exclude_users = NULL;
int session_fd = -1;
int r;
/* pam_syslog(handle, LOG_INFO, "pam-systemd initializing"); */
/* Make this a NOP on non-systemd systems */
if (sd_booted() <= 0)
return PAM_SUCCESS;
if (parse_argv(handle,
&debug) < 0) {
r = PAM_SESSION_ERR;
goto finish;
}
if (r != PAM_SUCCESS)
goto finish;
/* Make sure we don't enter a loop by talking to
* systemd-logind when it is actually waiting for the
* background to finish start-up. If the service is
* "systemd-shared" we simply set XDG_RUNTIME_DIR and
* leave. */
r = PAM_BUF_ERR;
goto finish;
}
r = parse_env_file(p, NEWLINE,
"RUNTIME", &rt,
NULL);
free(p);
if (r < 0 && r != -ENOENT) {
r = PAM_SESSION_ERR;
goto finish;
}
if (rt) {
if (r != PAM_SUCCESS) {
goto finish;
}
}
r = PAM_SUCCESS;
goto finish;
}
if (kill_processes)
if (!bus) {
r = PAM_SESSION_ERR;
goto finish;
}
"org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"CreateSession");
if (!m) {
r = PAM_BUF_ERR;
goto finish;
}
/* A tty with a colon is usually an X11 display, place
* there to show up in utmp. We rearrange things and
* don't pretend that an X display was a tty */
tty = "";
/* cron has been setting PAM_TTY to "cron" for a very long time
* and it cannot stop doing that for compatibility reasons. */
tty = "";
}
}
class = "user";
if (!dbus_message_append_args(m,
r = PAM_BUF_ERR;
goto finish;
}
if (r < 0) {
r = PAM_BUF_ERR;
goto finish;
}
if (r < 0) {
r = PAM_BUF_ERR;
goto finish;
}
kp = kill_processes;
r = PAM_BUF_ERR;
goto finish;
}
if (debug)
"uid=%u pid=%u service=%s type=%s seat=%s vtnr=%u tty=%s display=%s remote=%s remote_user=%s remote_host=%s",
if (!reply) {
r = PAM_SESSION_ERR;
goto finish;
}
r = PAM_SESSION_ERR;
goto finish;
}
if (debug)
"id=%s object_path=%s runtime_path=%s session_fd=%d seat=%s vtnr=%u",
if (r != PAM_SUCCESS) {
goto finish;
}
if (r != PAM_SUCCESS) {
goto finish;
}
if (r != PAM_SUCCESS) {
goto finish;
}
}
if (vtnr > 0) {
char buf[11];
if (r != PAM_SUCCESS) {
goto finish;
}
}
if (session_fd >= 0) {
if (r != PAM_SUCCESS) {
return r;
}
}
session_fd = -1;
r = PAM_SUCCESS;
if (bus) {
}
if (m)
if (reply)
if (session_fd >= 0)
return r;
}
int flags,
const void *p = NULL;
const char *id;
int r;
if (id) {
/* Before we go and close the FIFO we need to tell
* logind that this is a clean session shutdown, so
* that it doesn't just go and slaughter us
* immediately after closing the fd */
if (!bus) {
r = PAM_SESSION_ERR;
goto finish;
}
"org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"ReleaseSession");
if (!m) {
r = PAM_BUF_ERR;
goto finish;
}
if (!dbus_message_append_args(m,
r = PAM_BUF_ERR;
goto finish;
}
if (!reply) {
r = PAM_SESSION_ERR;
goto finish;
}
}
r = PAM_SUCCESS;
if (p)
if (bus) {
}
if (m)
if (reply)
return r;
}