From 6107a37ae0f8ad89ab6d2d36f93cc0d47f8bb47a Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Sun, 29 Sep 2024 18:26:07 -0400 Subject: project: Move server/client code into library Signed-off-by: Ian Moffett --- lib/libostp/auth.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 lib/libostp/auth.c (limited to 'lib/libostp/auth.c') diff --git a/lib/libostp/auth.c b/lib/libostp/auth.c new file mode 100644 index 0000000..d32c06a --- /dev/null +++ b/lib/libostp/auth.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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(struct ostp_session *sp, 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(sp->sockfd, 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(sp->sockfd, &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(sp->sockfd, &auth, sizeof(auth), session_key); + if (error < 0) { + printf("Failed to ACK user authentication with frame\n"); + return error; + } + return 0; +} + +static void +send_motd(struct ostp_session *sp, const unsigned char *session_key) +{ + char motd[] = MOTD; + + printf("Sending MOTD...\n"); + if (send_frame(sp->sockfd, motd, sizeof(motd), session_key) < 0) { + printf("Failed to session MOTD\n"); + } +} + +static int +session_run(struct ostp_session *sp, struct ostp_listener *lp, + const unsigned char *session_key) +{ + char buf[4096]; + size_t len; + + while (1) { + for (int i = 1; i < MAX_CLIENTS; ++i) { + if (lp->clients[i] <= 0) + continue; + if (FD_ISSET(lp->clients[i], &lp->client_fds) <= 0) + continue; + + len = recv_frame(lp->clients[i], sizeof(buf) - 1, session_key, buf); + if (len < 0) { + printf("recv_frame() failure, packet lost\n"); + continue; + } + if (len == 0) { + return 0; + } + if (lp->on_recv != NULL) { + lp->on_recv(sp, buf, len); + } + } + } +} + +int +handle_srq(struct ostp_session *sp, struct ostp_listener *lp, struct session_request *srq) +{ + struct x25519_keypair keypair; + unsigned char *session_key; + pid_t child; + 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("Generating keys...\n"); + + if (gen_x25519_keypair(&keypair) < 0) { + printf("Key generation failed!\n"); + return -1; + } + + /* Send back our our public key */ + error = send(sp->sockfd, keypair.pubkey, keypair.pubkey_len, 0); + if (error < 0) { + perror("Failed to send public key"); + return error; + } + + printf("Deriving session key...\n"); + error = gen_session_key(keypair.privkey, srq->pubkey, &session_key); + if (error < 0) { + return error; + } + + /* Try user auth, not needed if REQUIRE_USER_AUTH is 0 */ + if (passwd_auth(sp, session_key) != 0) { + return -1; + } + + /* Handle any requested session parameters */ + if ((error = negotiate_spw(sp, session_key)) < 0) { + free_session_key(session_key); + return error; + } + + send_motd(sp, session_key); + + /* Dispatch a thread and handle this session */ + child = fork(); + if (child == 0) { + session_run(sp, lp, session_key); + exit(0); + } + return 0; +} -- cgit v1.2.3