aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2024-09-28 01:10:13 -0400
committerIan Moffett <ian@osmora.org>2024-09-28 01:10:13 -0400
commit9a44a928ccebdceb5a4dd9a4d67168cc04d1227f (patch)
tree8f64888b89e9ffe6f5dd6fd541623b15184ccbb9
parent2229015eec1804cf33225fd28931a9e43e1fdf2e (diff)
ostp.d: auth: Add user authentication
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r--lib/include/defs.h4
-rw-r--r--lib/include/net/stpsession.h13
-rw-r--r--ostp.d/include/otconfig.h1
-rw-r--r--ostp.d/net/otd_auth.c96
-rw-r--r--setup.sh12
-rwxr-xr-xtools/pwcheck43
6 files changed, 169 insertions, 0 deletions
diff --git a/lib/include/defs.h b/lib/include/defs.h
index 1a022f9..e621e71 100644
--- a/lib/include/defs.h
+++ b/lib/include/defs.h
@@ -49,6 +49,10 @@
#define PAP_BAD_PERMS 0x02 /* SPW provided needs more permissions */
#define PAP_RESOURCE 0x03 /* Server has insufficient resources */
+/* Session auth code defs */
+#define AUTH_SUCCESS 0x00 /* Successful auth */
+#define AUTH_BAD_PW 0x01 /* Bad password */
+
/* Fixed paths */
#define OSMORA_TRUST "/etc/ostp/trusted_users.osmt"
diff --git a/lib/include/net/stpsession.h b/lib/include/net/stpsession.h
index 773d57b..aeed9cb 100644
--- a/lib/include/net/stpsession.h
+++ b/lib/include/net/stpsession.h
@@ -41,6 +41,9 @@
*/
#define MESSAGE_SIZE (1 << 12)
+/* Session Request option bits */
+#define SESSION_REQ_USER BIT(0)
+
/*
* The Session Request is sent from the client to the
* server and contains a HOP (hash, options, pubkey)
@@ -81,6 +84,16 @@ struct session_request {
} PACKED;
/*
+ * Structure containing user information
+ * for password protected channels.
+ */
+struct session_auth {
+ char username[256];
+ char password[64];
+ uint8_t code;
+};
+
+/*
* OSTP Message Frame containing an IV, AES
* GCM tag, payload length and payload
* with encrypted data.
diff --git a/ostp.d/include/otconfig.h b/ostp.d/include/otconfig.h
index 33e3314..9487556 100644
--- a/ostp.d/include/otconfig.h
+++ b/ostp.d/include/otconfig.h
@@ -35,6 +35,7 @@
#define CONNECTION_TIMEOUT 60 /* In seconds */
#define ENABLE_MOTD 1 /* Enable message of the day */
#define ARBITRATION_MAX 5 /* Maximum number of arbitration attempts */
+#define REQUIRE_USER_AUTH 1 /* 1: true, 0: false */
/* Message of the day */
#if defined(ENABLE_MOTD)
diff --git a/ostp.d/net/otd_auth.c b/ostp.d/net/otd_auth.c
index 6e757ae..67b4885 100644
--- a/ostp.d/net/otd_auth.c
+++ b/ostp.d/net/otd_auth.c
@@ -27,13 +27,16 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <sys/wait.h>
#include <arpa/inet.h>
#include <net/auth.h>
+#include <net/listen.h>
#include <net/param.h>
#include <net/stpsession.h>
#include <crypto/ecdh.h>
#include <otconfig.h>
#include <stdio.h>
+#include <unistd.h>
#define KEY_BYTE_WIDTH 32
@@ -62,6 +65,92 @@ send_motd(int client_fd, const unsigned char *session_key)
}
/*
+ * Check a password to see if it matches with
+ * the hash in /etc/shadow by using the pwcheck
+ * script. Returns 0 on success.
+ */
+static int
+pwcheck(char *username, char *pw)
+{
+ char *pwcheck = "/usr/local/bin/pwcheck";
+ pid_t pid;
+ char *args[] = {pwcheck, username, pw, NULL};
+ int status;
+
+ pid = fork();
+ if (pid == 0) {
+ execv(pwcheck, args);
+ }
+
+ if (waitpid(pid, &status, 0) < 0) {
+ printf("waidpid() failed\n");
+ return -1;
+ }
+
+ if (WIFEXITED(status)) {
+ return WEXITSTATUS(status);
+ }
+
+ return -1;
+}
+
+static int
+passwd_auth(int client_fd, const unsigned char *session_key)
+{
+ int error;
+ struct session_auth auth;
+ const size_t LEN = sizeof(auth);
+
+ if (!REQUIRE_USER_AUTH) {
+ return 0;
+ }
+
+ error = recv_frame(client_fd, sizeof(auth), session_key, &auth);
+ if (error < 0) {
+ return error;
+ }
+
+ if (pwcheck(auth.username, auth.password) != 0) {
+ printf("Got bad password for %s\n", auth.username);
+ auth.code = AUTH_BAD_PW;
+ error = send_frame(client_fd, &auth, sizeof(auth), session_key);
+ if (error < 0) {
+ printf("Failed to ACK user authentication with frame\n");
+ }
+ return -1;
+ }
+
+ auth.code = AUTH_SUCCESS;
+ error = send_frame(client_fd, &auth, sizeof(auth), session_key);
+ if (error < 0) {
+ printf("Failed to ACK user authentication with frame\n");
+ return error;
+ }
+ return 0;
+}
+
+static int
+client_echo(int client_fd, const unsigned char *session_key)
+{
+ char buf[4096];
+ int error;
+
+ error = recv_frame(client_fd, sizeof(buf) - 1, session_key, buf);
+ if (error < 0) {
+ return error;
+ }
+
+ /* Echo frame to all clients */
+ for (size_t i = 1; i < MAX_CLIENTS; ++i) {
+ if (clients[i] <= 0)
+ continue;
+
+ send_frame(clients[i], buf, sizeof(buf), session_key);
+ }
+
+ return 0;
+}
+/*
* Verify the session request packet and handle
* the rest.
*
@@ -75,6 +164,13 @@ handle_srq(int client_fd, struct session_request *srq)
unsigned char *session_key;
int error;
+ if (REQUIRE_USER_AUTH && !ISSET(srq->options, SESSION_REQ_USER)) {
+ printf("%x\n", srq->options);
+ printf("User authentication enforced but client 'U' bit not set\n");
+ printf("Closing connection...\n");
+ return -1;
+ }
+
printf("Got public key from peer: \n");
log_pubkey(srq->pubkey);
printf("Generating keys...\n");
diff --git a/setup.sh b/setup.sh
new file mode 100644
index 0000000..3ac16a1
--- /dev/null
+++ b/setup.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+set -e
+
+OTDPASSWD_LOC=/usr/local/bin/pwcheck
+
+if [[ $EUID -ne 0 ]]
+then
+ echo "Please run as root!"
+ exit 1
+fi
+
+cp tools/pwcheck $OTDPASSWD_LOC
diff --git a/tools/pwcheck b/tools/pwcheck
new file mode 100755
index 0000000..85cd6c3
--- /dev/null
+++ b/tools/pwcheck
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Get the current user's username
+USER=""
+PW=""
+
+if [[ $# -lt 2 ]]
+then
+ echo "Usage: pwcheck [username] [password]"
+ exit 1
+fi
+
+PW_HASH=""
+USER="$1"
+PW="$2"
+
+# Get the hashed password from /etc/shadow for the current user
+SHADOW_ENTRY=$(sudo grep "^$USER:" /etc/shadow)
+
+if [ -z "$SHADOW_ENTRY" ]; then
+ echo "User not found in /etc/shadow"
+ exit 1
+fi
+
+HASHED_PW=$(echo "$SHADOW_ENTRY" | cut -d':' -f2)
+SALT=$(echo "$HASHED_PW" | cut -d'$' -f3)
+ALGORITHM=$(echo "$HASHED_PW" | cut -d'$' -f2)
+
+# Yescrypt
+if [[ $ALGORITHM == "y" ]]
+then
+ HASHED_PW=$(echo "$SHADOW_ENTRY" | cut -d':' -f2)
+ SALT=$(echo "$HASHED_PW" | cut -d'$' -f4)
+ PW_HASH=$(mkpasswd "$PW" "\$y\$j9T\$$SALT")
+else
+ PW_HASH=$(echo "$PW" | openssl passwd -stdin -"$ALGORITHM" -salt "$SALT")
+fi
+
+if [ "$PW_HASH" == "$HASHED_PW" ]; then
+ exit 0
+else
+ exit 1
+fi