pam-module.c revision cc3773810855956bad92337cee8fa193584ab62e
/*-*- 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 Lesser General Public License as published by
the Free Software Foundation; either version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser 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 "util.h"
#include "audit.h"
#include "macro.h"
#include "strv.h"
#include "dbus-common.h"
#include "def.h"
#include "socket-util.h"
#include "fileio.h"
const char **class,
bool *debug) {
unsigned i;
for (i = 0; i < (unsigned) argc; i++) {
int k;
if (class)
if (k < 0) {
return k;
}
if (debug)
*debug = k;
} else {
return 0;
}
}
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;
}
_cleanup_free_ char *p = NULL;
int r;
union sockaddr_union sa = {
};
socklen_t l;
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)
return -errno;
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 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;
int session_fd = -1;
int r;
if (debug)
/* Make this a NOP on non-logind systems */
if (!logind_running())
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-user" 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 (!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,
* placed 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 probably shouldn't stop doing that
* for compatibility reasons. */
tty = "";
type = "unspecified";
/* ssh has been setting PAM_TTY to "ssh" for a very
* long time and probably shouldn't stop doing that
* for compatibility reasons. */
tty = "";
type ="tty";
}
/* If this fails vtnr will be 0, that's intended */
}
if (!type)
if (!dbus_message_append_args(m,
r = PAM_BUF_ERR;
goto finish;
}
r = PAM_BUF_ERR;
goto finish;
}
if (debug)
"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);
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 (r != PAM_SUCCESS) {
return r;
}
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 char *id;
int r;
/* Only release session if it wasn't pre-existing when we
* tried to create it */
/* 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;
}