Browse Source

* refactor connection auth

master
Alex 'AdUser' Z 3 years ago
parent
commit
bee237f261
  1. 99
      src/csocket.c
  2. 3
      src/csocket.h

99
src/csocket.c

@ -73,59 +73,61 @@ f2b_conn_destroy(f2b_conn_t *conn) {
free(conn);
}
void
f2b_conn_update_challenge(f2b_conn_t *conn) {
char buf[64] = "";
MD5_CTX md5;
memset(&md5, 0x0, sizeof(md5));
snprintf(buf, sizeof(buf), "%08lx+%ld", random(), time(NULL));
MD5Init(&md5);
MD5Update(&md5, buf, strlen(buf));
MD5Final(&md5);
strlcpy(conn->challenge, md5.string, sizeof(conn->challenge));
}
void
f2b_conn_send_unauth(f2b_conn_t *conn) {
f2b_buf_append(&conn->send, "-unauthorized: ", 0);
f2b_buf_append(&conn->send, conn->challenge, 0);
f2b_buf_append(&conn->send, "\n", 0);
}
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);
if ((conn->flags & CSOCKET_CONN_NEED_AUTH) == 0)
return true; /* not needed */
if (conn->flags & CSOCKET_CONN_AUTH_OK)
return true; /* already passed */
if (conn->flags & CSOCKET_CONN_AUTH_OK) {
f2b_buf_append(&conn->send, "+already authorized\n", 0);
return true;
}
if (cmd->type == CMD_AUTH) {
if (strcmp(cmd->args[1], "plain") == 0) {
if (strcmp(cmd->args[2], conn->password) == 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 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);
if (strcmp(cmd->args[1], "plain") == 0) {
if (strcmp(cmd->args[2], conn->password) == 0) {
conn->flags |= CSOCKET_CONN_AUTH_OK;
f2b_buf_append(&conn->send, "+ok\n", 0);
return true;
}
} /* else: other command */
if (!conn->challenge[0]) {
/* generate new nonce if empty */
snprintf(buf, sizeof(buf), "%08lx+%08lX", random(), random());
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, buf, strlen(buf));
MD5Update(&md5, conn->challenge, strlen(conn->challenge));
MD5Update(&md5, conn->password, strlen(conn->password));
MD5Final(&md5);
strlcpy(conn->challenge, md5.string, sizeof(conn->challenge));
if (strcmp(cmd->args[2], md5.string) == 0) {
conn->flags |= CSOCKET_CONN_AUTH_OK;
f2b_buf_append(&conn->send, "+ok\n", 0);
return true;
}
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);
}
f2b_buf_append(&conn->send, "-unauthorized: ", 0);
f2b_buf_append(&conn->send, conn->challenge, 0);
f2b_buf_append(&conn->send, "\n", 0);
f2b_conn_update_challenge(conn);
f2b_conn_send_unauth(conn);
return false;
}
@ -167,15 +169,21 @@ f2b_conn_process(f2b_conn_t *conn, bool in, void (*cb)(const f2b_cmd_t *cmd, f2b
}
f2b_log_msg(log_debug, "extracted line: %s", line);
if ((cmd = f2b_cmd_create(line)) != NULL) {
if (f2b_conn_check_auth(conn, cmd)) {
if (cmd->type == CMD_AUTH) {
f2b_conn_check_auth(conn, cmd);
} else if (conn->flags & CSOCKET_CONN_AUTH_OK) {
cb(cmd, &conn->send); /* handle command */
} else {
f2b_conn_send_unauth(conn);
}
f2b_cmd_destroy(cmd);
} else if (conn->flags & CSOCKET_CONN_AUTH_OK) {
f2b_buf_append(&conn->send, "-unknown command, try 'help'\n", 0);
} else {
f2b_buf_append(&conn->send, "-can't parse input, try 'help'\n", 0);
f2b_conn_send_unauth(conn);
}
free(line);
}
} /* while (f2b_buf_extract()) */
if (conn->recv.used >= conn->recv.size) {
f2b_log_msg(log_error, "drop connection on socket %d, recv buffer overflow", conn->sock);
return -1;
@ -361,7 +369,7 @@ f2b_csocket_create(f2b_config_section_t *config) {
return NULL;
}
if (need_pass && strcmp(csock->password, "") == 0) {
snprintf(csock->password, sizeof(csock->password), "%lx+%lX", random(), random());
snprintf(csock->password, sizeof(csock->password), "%lx+%ld", random(), time(NULL));
f2b_log_msg(log_info, "set random password for control socket: %s", csock->password);
}
return csock;
@ -462,6 +470,7 @@ f2b_csocket_poll(f2b_csock_t *csock, void (*cb)(const f2b_cmd_t *cmd, f2b_buf_t
} else {
f2b_log_msg(log_debug, "new local connection from uid %d, socket %d", peer.uid, sock);
}
conn->flags |= CSOCKET_CONN_AUTH_OK;
} else /* CSOCKET_CONN_TYPE_INET */ {
if (addr.ss_family == AF_INET) {
inet_ntop(AF_INET, &(((struct sockaddr_in *) &addr)->sin_addr), conn->peer, sizeof(conn->peer));
@ -469,10 +478,10 @@ f2b_csocket_poll(f2b_csock_t *csock, void (*cb)(const f2b_cmd_t *cmd, f2b_buf_t
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *) &addr)->sin6_addr), conn->peer, sizeof(conn->peer));
}
f2b_log_msg(log_debug, "new remote connection from %s, socket %d", conn->peer, sock);
conn->flags |= CSOCKET_CONN_NEED_AUTH;
}
conn->sock = sock;
conn->password = csock->password;
f2b_conn_update_challenge(conn);
csock->clients[cnum] = conn;
} else {
f2b_log_msg(log_error, "can't create new connection");

3
src/csocket.h

@ -14,8 +14,7 @@
/* connection flags */
#define CSOCKET_CONN_TYPE_UNIX 0x01
#define CSOCKET_CONN_TYPE_INET 0x02
#define CSOCKET_CONN_NEED_AUTH 0x04
#define CSOCKET_CONN_AUTH_OK 0x08
#define CSOCKET_CONN_AUTH_OK 0x04
typedef struct f2b_csock_t f2b_csock_t;

Loading…
Cancel
Save