From c2a7a39daa657bf5732a2c8ac82472ef8e474d6a Mon Sep 17 00:00:00 2001 From: Alex 'AdUser' Z Date: Wed, 24 Mar 2021 16:17:03 +1000 Subject: [PATCH] * challenge auth for csocket --- src/CMakeLists.txt | 4 ++-- src/commands.c | 5 ++++- src/csocket.c | 31 ++++++++++++++++++++++++++++++- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c4b6727..6883a6b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,7 +4,7 @@ set(SOURCES "daemon.c" "strlcpy.c" "config.c" "buf.c" "log.c" "matches.c" "ipadd "appconfig.c" "statefile.c" "source.c" "filter.c" "backend.c" "jail.c") if (WITH_CSOCKET) - list(APPEND SOURCES "commands.c" "csocket.c") + list(APPEND SOURCES "md5.c" "commands.c" "csocket.c") add_definitions("-DWITH_CSOCKET") endif () @@ -30,7 +30,7 @@ add_executable("f2b-filter-test" ${SOURCES}) set(SOURCES "strlcpy.c" "backend-test.c" "log.c" "config.c" "backend.c") add_executable("f2b-backend-test" ${SOURCES}) -set(SOURCES "strlcpy.c" "csocket-test.c" "log.c" "buf.c" "config.c" "commands.c" "csocket.c") +set(SOURCES "strlcpy.c" "csocket-test.c" "log.c" "buf.c" "config.c" "commands.c" "csocket.c" "md5.c") add_executable("f2b-csocket-test" ${SOURCES}) if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") diff --git a/src/commands.c b/src/commands.c index b5bf862..07c64b3 100644 --- a/src/commands.c +++ b/src/commands.c @@ -24,7 +24,7 @@ struct cmd_desc { .type = CMD_AUTH, .argc = 2, .tokenc = 3, .tokens = { "auth", "", "", NULL }, - .help = "Check authorization (available types is: plain)", + .help = "Check authorization (available types is: plain, challenge)", }, { .type = CMD_STATUS, .argc = 0, .tokenc = 1, @@ -214,6 +214,9 @@ f2b_cmd_parse(f2b_cmd_t *cmd, const char *src) { if (cmd->argc == 3 && strcmp(cmd->args[1], "plain") == 0) { cmd->type = CMD_AUTH; return true; } + if (cmd->argc == 3 && strcmp(cmd->args[1], "challenge") == 0) { + cmd->type = CMD_AUTH; return true; + } } else if (strcmp(cmd->args[0], "log") == 0 && cmd->argc > 1) { if (cmd->argc == 2 && strcmp(cmd->args[1], "rotate") == 0) { cmd->type = CMD_LOG_ROTATE; return true; diff --git a/src/csocket.c b/src/csocket.c index dbcfbc0..1a89e5e 100644 --- a/src/csocket.c +++ b/src/csocket.c @@ -8,6 +8,7 @@ #include "config.h" #include "buf.h" #include "log.h" +#include "md5.h" #include "commands.h" #include "csocket.h" @@ -24,6 +25,7 @@ typedef struct f2b_conn_t { int flags; const char *password; char peer[40]; /* remote address ipv4/ipv6 */ + char challenge[40]; /* md5() of random string, nonce for auth */ } f2b_conn_t; typedef struct f2b_sock_t { @@ -73,6 +75,9 @@ f2b_conn_destroy(f2b_conn_t *conn) { bool f2b_conn_check_auth(f2b_conn_t *conn, f2b_cmd_t *cmd) { + char buf[64] = ""; + MD5_CTX md5; + assert(conn != NULL); assert(cmd != NULL); @@ -91,12 +96,36 @@ f2b_conn_check_auth(f2b_conn_t *conn, f2b_cmd_t *cmd) { } else { f2b_log_msg(log_error, "csocket auth failure from %s: password mismatch", conn->peer); } + } else if (strcmp(cmd->args[1], "challenge") == 0) { + MD5Init(&md5); + MD5Update(&md5, conn->challenge, strlen(conn->challenge)); + MD5Update(&md5, conn->password, strlen(conn->password)); + MD5Final(&md5); + memset(conn->challenge, 0x0, sizeof(conn->challenge)); /* reset */ + if (strcmp(cmd->args[2], md5.string) == 0) { + conn->flags |= CSOCKET_CONN_AUTH_OK; + f2b_buf_append(&conn->send, "+ok\n", 0); + return true; + } else { + f2b_log_msg(log_error, "csocket auth failure from %s: password mismatch", conn->peer); + } } else { f2b_log_msg(log_error, "csocket auth failure from %s: unknown auth method", conn->peer); } } /* else: other command */ - f2b_buf_append(&conn->send, "-unauthorized\n", 0); + if (!conn->challenge[0]) { + /* generate new nonce if empty */ + snprintf(buf, sizeof(buf), "%08lx+%08lX", random(), random()); + MD5Init(&md5); + MD5Update(&md5, buf, strlen(buf)); + MD5Final(&md5); + strlcpy(conn->challenge, md5.string, sizeof(conn->challenge)); + } + + f2b_buf_append(&conn->send, "-unauthorized: ", 0); + f2b_buf_append(&conn->send, conn->challenge, 0); + f2b_buf_append(&conn->send, "\n", 0); return false; }