summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: a9ae0d1)
raw | patch | inline | side by side (parent: a9ae0d1)
author | Sebastian Harl <sh@tokkee.org> | |
Tue, 9 Dec 2014 14:19:47 +0000 (15:19 +0100) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Tue, 9 Dec 2014 14:19:47 +0000 (15:19 +0100) |
Then, only allow that user to authenticate against the daemon. That is, use
the same as PostgreSQL's "peer" authentication for all connections.
the same as PostgreSQL's "peer" authentication for all connections.
diff --git a/configure.ac b/configure.ac
index 088a4b59fc994ad313dbd9540b1fc70901808b6d..baf1137b530197b1689be9106ff4f9751b70377b 100644 (file)
--- a/configure.ac
+++ b/configure.ac
m4_divert_once([HELP_ENABLE], [
Build dependencies:])
+AC_CHECK_HEADERS([ucred.h])
+dnl On OpenBSD, sys/param.h is required for sys/ucred.h.
+AC_CHECK_HEADERS([sys/ucred.h], [], [],
+ [[ #include <sys/param.h> ]])
+
+AC_CHECK_TYPES([struct ucred],
+ [have_struct_ucred="yes"], [have_struct_ucred="no"],
+ [[
+#include <sys/socket.h>
+#include <sys/param.h>
+#if HAVE_UCRED_H
+# include <ucred.h>
+#endif
+ ]])
+
+if test "x$have_struct_ucred" != "xyes"; then
+ AC_MSG_CHECKING([for struct ucred when using _GNU_SOURCE])
+ orig_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -D_GNU_SOURCE"
+ dnl Don't reuse AC_CHECK_HEADERS; for one it'll use the cached value
+ dnl but also, it will print the "checking for" message a second time.
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[
+#include <sys/socket.h>
+#include <sys/param.h>
+#if HAVE_UCRED_H
+# include <ucred.h>
+#endif
+ ]],
+ [if (sizeof(struct ucred)) return 0;]
+ )],
+ [have_struct_ucred="yes"], [have_struct_ucred="no"])
+ CFLAGS="$orig_CFLAGS"
+ if test "x$have_struct_ucred" = "xyes"; then
+ AC_DEFINE([_GNU_SOURCE], 1, [Define to enable GNU features.])
+ fi
+ AC_MSG_RESULT([$have_struct_ucred])
+fi
+
dnl Testing.
PKG_CHECK_MODULES([CHECK], [check >= 0.9.4],
[unit_tests="yes"], [unit_tests="no"])
AC_MSG_CHECKING([for facter::facts::collection in -lfacter])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
- [[[ #include <facter/facts/collection.hpp> ]]],
- [[[
+ [[ #include <facter/facts/collection.hpp> ]],
+ [[
facter::facts::collection facts;
facts.add_default_facts();
- ]]]
+ ]]
)],
[TEST_LIBS=$TEST_LIBS -lfacter],
[have_libfacter="yes"],
diff --git a/src/client/sock.c b/src/client/sock.c
index ef35166bab13162e84156facbd75d83fdd937b85..533e9e31b62c16457f36ae1e844a450251c26c51 100644 (file)
--- a/src/client/sock.c
+++ b/src/client/sock.c
"for server response");
if (rstatus == SDB_CONNECTION_ERROR) {
- sdb_log(SDB_LOG_ERR, "Access denied for user '%s'", username);
+ sdb_log(SDB_LOG_ERR, "Access denied for user '%s': %s",
+ username, sdb_strbuf_string(buf));
status = -((int)rstatus);
}
else if (rstatus != SDB_CONNECTION_OK) {
index e384bafa98297a7cf46c9283dee7b70a9c484dab..b27b3dd28bfbfd0324941d1861bc2bdd5d60a8ca 100644 (file)
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
#include "sysdb.h"
#include "core/object.h"
#include "core/plugin.h"
#include <stdlib.h>
#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/param.h>
+
+#ifdef HAVE_UCRED_H
+# include <ucred.h>
+#endif
+#ifdef HAVE_SYS_UCRED_H
+# include <sys/ucred.h>
+#endif
+
+#include <pwd.h>
+
#include <pthread.h>
/*
#define CONN_FD_PREFIX "conn#"
#define CONN_FD_PLACEHOLDER "XXXXXXX"
+/* XXX: only supports UNIX sockets so far */
+static char *
+peer(int sockfd)
+{
+ uid_t uid;
+
+ struct passwd pw_entry;
+ struct passwd *result = NULL;
+ char buf[1024];
+
+#ifdef SO_PEERCRED
+ struct ucred cred;
+ socklen_t len = sizeof(cred);
+
+ if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cred, &len)
+ || (len != sizeof(cred)))
+ return NULL;
+ uid = cred.uid;
+#else /* SO_PEERCRED */
+ errno = ENOSYS;
+ return NULL;
+#endif
+
+ memset(&pw_entry, 0, sizeof(pw_entry));
+ if (getpwuid_r(uid, &pw_entry, buf, sizeof(buf), &result)
+ || (! result))
+ return NULL;
+ return strdup(result->pw_name);
+} /* peer */
+
static int
connection_init(sdb_object_t *obj, va_list ap)
{
return -1;
}
+ conn->username = peer(conn->fd);
+ if (! conn->username) {
+ char buf[1024];
+ sdb_log(SDB_LOG_ERR, "frontend: Failed to retrieve peer for "
+ "connection conn#%i: %s", conn->fd,
+ sdb_strerror(errno, buf, sizeof(buf)));
+ return -1;
+ }
+ conn->ready = 0;
+
sdb_log(SDB_LOG_DEBUG, "frontend: Accepted connection on fd=%i",
conn->fd);
diff --git a/src/frontend/session.c b/src/frontend/session.c
index b0fc7803e2a0e23ab53a05cc6a1c694c4251b824..ab45cdd17c30cb154a7cf051cf940ba11e47e4b0 100644 (file)
--- a/src/frontend/session.c
+++ b/src/frontend/session.c
int
sdb_fe_session_start(sdb_conn_t *conn)
{
- const char *username;
+ char username[sdb_strbuf_len(conn->buf) + 1];
+ const char *tmp;
- if ((! conn) || (conn->username))
+ if ((! conn) || (conn->cmd != SDB_CONNECTION_STARTUP))
return -1;
- if (conn->cmd != SDB_CONNECTION_STARTUP)
- return -1;
-
- username = sdb_strbuf_string(conn->buf);
- if ((! username) || (! conn->cmd_len) || (! *username)) {
+ tmp = sdb_strbuf_string(conn->buf);
+ if ((! tmp) || (! conn->cmd_len) || (! *tmp)) {
sdb_strbuf_sprintf(conn->errbuf, "Invalid empty username");
return -1;
}
+ strncpy(username, tmp, conn->cmd_len);
+ username[conn->cmd_len] = '\0';
- /* XXX: for now, simply accept all connections */
- conn->username = strndup(username, conn->cmd_len);
if (! conn->username) {
- sdb_strbuf_sprintf(conn->errbuf, "Authentication failed");
+ /* We couldn't determine the remote peer when setting up the
+ * connection; TODO: add support for password authentication */
+ sdb_strbuf_sprintf(conn->errbuf, "Password authentication "
+ "not supported");
return -1;
}
+ if (strcmp(conn->username, username)) {
+ sdb_strbuf_sprintf(conn->errbuf, "%s cannot act on behalf of %s",
+ conn->username, username);
+ return -1;
+ }
+
sdb_connection_send(conn, SDB_CONNECTION_OK, 0, NULL);
conn->ready = 1;
return 0;
diff --git a/t/integration/query.sh b/t/integration/query.sh
index 39522cf9be6c09928952f121b621b6121286e54a..5536c701c9c517eefd3882518e0e2eee1683a88a 100755 (executable)
--- a/t/integration/query.sh
+++ b/t/integration/query.sh
wait_for_sysdbd
sleep 3
+# Invalid user.
+output="$( run_sysdb_nouser -H "$SOCKET_FILE" \
+ -U $SYSDB_USER-invalid -c 'LIST hosts' 2>&1 )" && exit 1
+echo "$output" | grep -F 'Access denied'
+
# On parse errors, expect a non-zero exit code.
output="$( run_sysdb -H "$SOCKET_FILE" -c INVALID )" && exit 1
echo "$output" | grep "Failed to parse query 'INVALID'"
index 0cc1931770d15bb0b86a46c6a9f6ad23d3b479d1..f6898e4678a9359e7e3b78949e095f8d2f36e9fc 100644 (file)
SOCKET_FILE="$TESTDIR/sock"
PLUGIN_DIR="$TESTDIR"
+SYSDB_USER="$( id -un )"
+
function run_sysdb() {
- $MEMCHECK "$TESTDIR/sysdb" -U mockuser "$@"
+ $MEMCHECK "$TESTDIR/sysdb" -U $SYSDB_USER "$@"
+}
+
+function run_sysdb_nouser() {
+ $MEMCHECK "$TESTDIR/sysdb" "$@"
}
function run_sysdbd() {
index 77828e6a8c4220d482a1eaaf69c6ec03b142fca0..13ae221a0f509e6f8402c2c5c10e838f4df8b2ef 100644 (file)
#include "frontend/connection.h"
#include "frontend/connection-private.h"
#include "utils/proto.h"
+#include "utils/os.h"
#include "libsysdb_test.h"
#include "utils/strbuf.h"
+#include <assert.h>
#include <check.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
+static char username[1024];
+
/*
* private helper functions
*/
unlink(tmp_file);
+ conn->username = strdup(username);
+ assert(conn->username);
+
conn->cmd = SDB_CONNECTION_IDLE;
conn->cmd_len = 0;
return conn;
{
ssize_t check, expected;
- expected = 2 * sizeof(uint32_t) + strlen("fakeuser");
+ expected = 2 * sizeof(uint32_t) + strlen(username);
check = sdb_connection_send(conn, SDB_CONNECTION_STARTUP,
- (uint32_t)strlen("fakeuser"), "fakeuser");
+ (uint32_t)strlen(username), username);
fail_unless(check == expected,
- "sdb_connection_send(STARTUP, fakeuser) = %zi; expected: %zi",
- check, expected);
+ "sdb_connection_send(STARTUP, %s) = %zi; expected: %zi",
+ username, check, expected);
mock_conn_rewind(conn);
check = sdb_connection_read(conn);
fail_unless(sdb_strbuf_len(conn->errbuf) == 0,
"sdb_connection_read() left %zu bytes in the error "
- "buffer; expected: 0", sdb_strbuf_len(conn->errbuf));
+ "buffer (%s); expected: 0", sdb_strbuf_len(conn->errbuf),
+ sdb_strbuf_string(conn->errbuf));
mock_conn_truncate(conn);
} /* connection_startup */
{ UINT32_MAX, NULL, NULL },
{ SDB_CONNECTION_IDLE, "fakedata", "Authentication required" },
{ SDB_CONNECTION_PING, NULL, "Authentication required" },
- { SDB_CONNECTION_STARTUP, "fakeuser", NULL },
+ { SDB_CONNECTION_STARTUP, username, NULL },
{ SDB_CONNECTION_PING, NULL, NULL },
{ SDB_CONNECTION_IDLE, NULL, "Invalid command 0" },
{ SDB_CONNECTION_PING, "fakedata", NULL },
else
fail_unless(sdb_strbuf_len(conn->errbuf) == 0,
"sdb_connection_read() left %zu bytes in the error "
- "buffer; expected: 0", sdb_strbuf_len(conn->errbuf));
+ "buffer (%s); expected: 0", sdb_strbuf_len(conn->errbuf),
+ sdb_strbuf_string(conn->errbuf));
}
mock_conn_destroy(conn);
Suite *s = suite_create("frontend::connection");
TCase *tc;
+ char *tmp = sdb_get_current_user();
+ assert(tmp);
+ strcpy(username, tmp);
+ free(tmp);
+
tc = tcase_create("core");
tcase_add_test(tc, test_conn_accept);
tcase_add_test(tc, test_conn_setup);
index c28781ea051f815cd739fe3b4df23501904dbd00..82a1daf7b6986a4ae4746dcfd151947a6db39aa5 100644 (file)
#endif /* HAVE_CONFIG_H */
/* required for fopencookie support */
-#define _GNU_SOURCE
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
#include "utils/unixsock.h"
#include "libsysdb_test.h"