Browse Source

* refactor connection auth

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

3
src/csocket.h

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

Loading…
Cancel
Save