summaryrefslogtreecommitdiffstats
path: root/auth/socket/socket-auth.c
diff options
context:
space:
mode:
authorDavid Sommerseth <dazo@users.sourceforge.net>2013-06-08 02:32:34 +0200
committerDavid Sommerseth <dazo@users.sourceforge.net>2013-06-09 01:03:29 +0200
commit6554cba9441de42e0c5c455b16fb5f6b39c19e28 (patch)
tree027ed605d3c5556bba853018fd6eb6cf18effc24 /auth/socket/socket-auth.c
parentd7b486079a77beb883e3c5e39842dd5c180f3b7b (diff)
downloadeurephia-6554cba9441de42e0c5c455b16fb5f6b39c19e28.tar.gz
eurephia-6554cba9441de42e0c5c455b16fb5f6b39c19e28.tar.xz
eurephia-6554cba9441de42e0c5c455b16fb5f6b39c19e28.zip
auth: Added socket-auth module
This can authenticate username/passwords via a file socket to an authentication service. A simple authentication service written in Python is added as well. Signed-off-by: David Sommerseth <dazo@users.sourceforge.net>
Diffstat (limited to 'auth/socket/socket-auth.c')
-rw-r--r--auth/socket/socket-auth.c224
1 files changed, 224 insertions, 0 deletions
diff --git a/auth/socket/socket-auth.c b/auth/socket/socket-auth.c
new file mode 100644
index 0000000..41396fb
--- /dev/null
+++ b/auth/socket/socket-auth.c
@@ -0,0 +1,224 @@
+/* socket-auth.c -- Authenticates user/password against a socket service
+ *
+ * The socket service retrieves the username and password and replies with
+ * PASS or FAIL. See the demo-auth-server.py for more info
+ *
+ * Copyright (C) 2013 David Sommerseth <dazo@users.sourceforge.net>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * @file socket-auth.c
+ * @author David Sommerseth <dazo@users.sourceforge.net>
+ * @date 2013-06-08
+ *
+ * @brief Authenticate users using a socket based auth server
+ */
+
+/*
+ * The wire protocol for the socket service is:
+ *
+ * The client sends:
+ * 1 byte - lenght of username
+ * x bytes - the username
+ * 1 byte - lenght of password
+ * x bytes - the password
+ *
+ * And now the server is expected to reply with:
+ * 4 bytes - containing the string FAIL or PASS
+ *
+ */
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <eurephia_nullsafe.h>
+#include <eurephia_context.h>
+#include <eurephia_log.h>
+#include <eurephia_authplugin_driver.h>
+
+/*
+ * INTERNAL VARIABLES AND FUNCTIONS
+ */
+
+static int authservfd = -1;
+static struct sockaddr_un sockaddr;
+
+/**
+ * Send data to the remote end according to the wire protocol
+ * where the first byte is the length of data to be sent. Maximum
+ * 127 bytes can be transferred.
+ *
+ * @param fd Socket fd to send the data to
+ * @param msg Pointer to the string to be sent
+ *
+ * @return Returns 1 on success, otherwise 0
+ */
+static int send_data(int fd, const char *msg)
+{
+ int msglen = strlen(msg);
+ char buf[130];
+
+ memset(&buf, 0, 130);
+ if( msglen > 127 ) {
+ msglen = 127;
+ }
+ snprintf(buf, msglen+1, "%c", (int) strlen(msg));
+ if (write(fd, buf, strlen(buf)) != strlen(buf)) {
+ return 0;
+ }
+
+ snprintf(buf, msglen+1, "%s", msg);
+ if (write(fd, buf, strlen(buf)) != strlen(buf)) {
+ return 0;
+ }
+ return 1;
+}
+
+
+/**
+ * Reads the server response and parses it. Anything except of 'PASS' is
+ * handled as a failure. But it expects the response to alwyas be 4 bytes.
+ *
+ * @param fd Socket fd where to read the response from
+ *
+ * @returns Returns 1 on successful authentication, otherwise 0. If less than 4 bytes
+ * was read it will return -1. In this case, it might be wise to reconnect to
+ * the server.
+ */
+static int parse_result(int fd)
+{
+ char buf[6];
+
+ memset(&buf, 0, 6);
+ int r = read(fd, &buf, 4);
+
+ if( r == 4 ) {
+ return strcmp(buf, "PASS") == 0;
+ }
+ return -1;
+}
+
+
+/**
+ * Sends username and password via the socket to the authentication server and
+ * parses the result back.
+ *
+ * @param fd Socket fd to the authentication server
+ * @param username Username to be authenticated
+ * @param passwd Matching password to the username
+ *
+ * @returns See parse_result() for valid result codes.
+ */
+static int authenticate_user(int fd, const char *username, const char *passwd)
+{
+ if( !send_data(fd, username) ) {
+ return 0;
+ }
+ if( !send_data(fd, passwd) ) {
+ return 0;
+ }
+ return parse_result(fd);
+}
+
+
+/*
+ * Required plug-in functions
+ */
+
+static ePluginInfo pluginfo = { .name = "socket-auth plug-in",
+ .version = "1.0",
+ .copyright = "2013 (C) David Sommerseth <dazo@users.sourceforge.net>",
+ .pluginType = eptAUTH,
+ .APIversion = 1 };
+
+
+/**
+ * @copydoc PluginInfo()
+ */
+ePluginInfo * PluginInfo()
+{
+ return &pluginfo;
+}
+
+/**
+ * @copydoc PluginInit()
+ */
+int PluginInit(eurephiaCTX *ctx, const char *args)
+{
+ authservfd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if ( authservfd == -1 ) {
+ eurephia_log(ctx, LOG_FATAL, 0, "Failed to initialise socket to the socket-auth server");
+ return 0;
+ }
+
+ memset(&sockaddr, 0, sizeof(struct sockaddr_un));
+ sockaddr.sun_family = AF_UNIX;
+ strncpy(sockaddr.sun_path, args, sizeof(sockaddr.sun_path)-1);
+
+ if( connect(authservfd, (struct sockaddr*)&sockaddr, sizeof(struct sockaddr_un)) == -1) {
+ eurephia_log(ctx, LOG_FATAL, 0, "Failed to connect to the socket-auth server");
+ close(authservfd);
+ authservfd = -1;
+ return 0;
+ }
+
+ eurephia_log(ctx, LOG_INFO, 0, "socket-auth connected via %s", args);
+ return 1;
+}
+
+
+/**
+ * @copydoc PluginClose()
+ */
+void PluginClose(eurephiaCTX *ctx)
+{
+ send_data(authservfd, "***SHUTDOWN***");
+ close(authservfd);
+ eurephia_log(ctx, LOG_INFO, 0, "Disconnected from auth-socket");
+}
+
+
+/**
+ * @copydoc AuthenticateUser()
+ */
+eAuthResult * AuthenticateUser(eurephiaCTX *ctx, const char *username, const char *passwd)
+{
+ eAuthResult *ret = NULL;
+ int authres = -2;
+
+ DEBUG(ctx, 20, "socket-auth:AuthenticateUser('%s', xxxxxx)", username);
+
+ ret = malloc_nullsafe(ctx, sizeof(eAuthResult)+2);
+ authres = authenticate_user(authservfd, username, passwd);
+ if( authres < 0 ) {
+ ret->status = eAUTH_PLGERROR;
+ ret->msg = strdup("Failed communicating with auth-server");
+ } else if( authres == 0 ) {
+ ret->status = eAUTH_FAILED;
+ ret->msg = strdup("Wrong password");
+ } else if( authres == 1 ) {
+ ret->status = eAUTH_SUCCESS;
+ } else {
+ // This should never ever happen
+ ret->status = eAUTH_PLGERROR;
+ ret->msg = strdup("Unknown result code");
+ }
+ return ret;
+}