diff options
| author | Ian Moffett <ian@osmora.org> | 2024-09-28 01:10:13 -0400 | 
|---|---|---|
| committer | Ian Moffett <ian@osmora.org> | 2024-09-28 01:10:13 -0400 | 
| commit | 9a44a928ccebdceb5a4dd9a4d67168cc04d1227f (patch) | |
| tree | 8f64888b89e9ffe6f5dd6fd541623b15184ccbb9 | |
| parent | 2229015eec1804cf33225fd28931a9e43e1fdf2e (diff) | |
ostp.d: auth: Add user authentication
Signed-off-by: Ian Moffett <ian@osmora.org>
| -rw-r--r-- | lib/include/defs.h | 4 | ||||
| -rw-r--r-- | lib/include/net/stpsession.h | 13 | ||||
| -rw-r--r-- | ostp.d/include/otconfig.h | 1 | ||||
| -rw-r--r-- | ostp.d/net/otd_auth.c | 96 | ||||
| -rw-r--r-- | setup.sh | 12 | ||||
| -rwxr-xr-x | tools/pwcheck | 43 | 
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 | 
