mirror of
https://github.com/ntop/n2n.git
synced 2024-09-20 00:51:10 +02:00
fortified user/pw auth scheme (#731)
This commit is contained in:
parent
045f6a7386
commit
84d0991977
|
@ -105,6 +105,9 @@ enum sn_purge{SN_PURGEABLE = 0, SN_UNPURGEABLE = 1};
|
||||||
#define HEADER_ENCRYPTION_NONE 1
|
#define HEADER_ENCRYPTION_NONE 1
|
||||||
#define HEADER_ENCRYPTION_ENABLED 2
|
#define HEADER_ENCRYPTION_ENABLED 2
|
||||||
|
|
||||||
|
/* REGISTER_SUPER_ACK packet hash length with user/pw auth, up to 16 bytes */
|
||||||
|
#define N2N_REG_SUP_HASH_CHECK_LEN 16
|
||||||
|
|
||||||
#define DEFAULT_MTU 1290
|
#define DEFAULT_MTU 1290
|
||||||
|
|
||||||
#define HASH_ADD_PEER(head,add) \
|
#define HASH_ADD_PEER(head,add) \
|
||||||
|
|
|
@ -1141,6 +1141,7 @@ void send_query_peer (n2n_edge_t * eee,
|
||||||
void send_register_super (n2n_edge_t *eee) {
|
void send_register_super (n2n_edge_t *eee) {
|
||||||
|
|
||||||
uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0};
|
uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0};
|
||||||
|
uint8_t hash_buf[16] = {0};
|
||||||
size_t idx;
|
size_t idx;
|
||||||
/* ssize_t sent; */
|
/* ssize_t sent; */
|
||||||
n2n_common_t cmn;
|
n2n_common_t cmn;
|
||||||
|
@ -1172,11 +1173,18 @@ void send_register_super (n2n_edge_t *eee) {
|
||||||
traceEvent(TRACE_DEBUG, "send REGISTER_SUPER to %s",
|
traceEvent(TRACE_DEBUG, "send REGISTER_SUPER to %s",
|
||||||
sock_to_cstr(sockbuf, &(eee->curr_sn->sock)));
|
sock_to_cstr(sockbuf, &(eee->curr_sn->sock)));
|
||||||
|
|
||||||
if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED)
|
if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) {
|
||||||
packet_header_encrypt(pktbuf, idx, idx,
|
packet_header_encrypt(pktbuf, idx, idx,
|
||||||
eee->conf.header_encryption_ctx_static, eee->conf.header_iv_ctx_static,
|
eee->conf.header_encryption_ctx_static, eee->conf.header_iv_ctx_static,
|
||||||
time_stamp());
|
time_stamp());
|
||||||
|
|
||||||
|
if(eee->conf.shared_secret) {
|
||||||
|
pearson_hash_128(hash_buf, pktbuf, idx);
|
||||||
|
speck_128_encrypt(hash_buf, (speck_context_t*)eee->conf.shared_secret_ctx);
|
||||||
|
encode_buf(pktbuf, &idx, hash_buf, N2N_REG_SUP_HASH_CHECK_LEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* sent = */ sendto_sock(eee, pktbuf, idx, &(eee->curr_sn->sock));
|
/* sent = */ sendto_sock(eee, pktbuf, idx, &(eee->curr_sn->sock));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2259,6 +2267,7 @@ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const
|
||||||
n2n_sock_str_t sockbuf2; /* don't clobber sockbuf1 if writing two addresses to trace */
|
n2n_sock_str_t sockbuf2; /* don't clobber sockbuf1 if writing two addresses to trace */
|
||||||
macstr_t mac_buf1;
|
macstr_t mac_buf1;
|
||||||
macstr_t mac_buf2;
|
macstr_t mac_buf2;
|
||||||
|
uint8_t hash_buf[16];
|
||||||
size_t rem;
|
size_t rem;
|
||||||
size_t idx;
|
size_t idx;
|
||||||
size_t msg_type;
|
size_t msg_type;
|
||||||
|
@ -2295,16 +2304,24 @@ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const
|
||||||
|
|
||||||
if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) {
|
if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) {
|
||||||
// match with static (1) or dynamic (2) ctx?
|
// match with static (1) or dynamic (2) ctx?
|
||||||
header_enc = packet_header_decrypt(udp_buf, udp_size,
|
// check dynamic first as it is identical to static in normal header encryption mode
|
||||||
(char *)eee->conf.community_name,
|
if(packet_header_decrypt(udp_buf, udp_size,
|
||||||
eee->conf.header_encryption_ctx_static, eee->conf.header_iv_ctx_static,
|
|
||||||
&stamp);
|
|
||||||
if(!header_enc)
|
|
||||||
if(packet_header_decrypt(udp_buf, udp_size,
|
|
||||||
(char *)eee->conf.community_name,
|
(char *)eee->conf.community_name,
|
||||||
eee->conf.header_encryption_ctx_dynamic, eee->conf.header_iv_ctx_dynamic,
|
eee->conf.header_encryption_ctx_dynamic, eee->conf.header_iv_ctx_dynamic,
|
||||||
&stamp)) {
|
&stamp)) {
|
||||||
header_enc = 2;
|
header_enc = 2; /* not accurate with normal header encryption but does not matter */
|
||||||
|
}
|
||||||
|
if(!header_enc) {
|
||||||
|
// check static now (very likely to be REGISTER_SUPER_ACK, REGISTER_SUPER_NAK or invalid)
|
||||||
|
if(eee->conf.shared_secret) {
|
||||||
|
// hash the still encrypted packet to eventually be able to check it later (required for REGISTER_SUPER_ACK with user/pw auth)
|
||||||
|
pearson_hash_128(hash_buf, udp_buf, max(0, (int)udp_size - (int)N2N_REG_SUP_HASH_CHECK_LEN));
|
||||||
|
}
|
||||||
|
header_enc = packet_header_decrypt(udp_buf, max(0, (int)udp_size - (int)N2N_REG_SUP_HASH_CHECK_LEN),
|
||||||
|
(char *)eee->conf.community_name,
|
||||||
|
eee->conf.header_encryption_ctx_static, eee->conf.header_iv_ctx_static,
|
||||||
|
&stamp);
|
||||||
|
header_enc = 1;
|
||||||
}
|
}
|
||||||
if(!header_enc) {
|
if(!header_enc) {
|
||||||
traceEvent(TRACE_DEBUG, "readFromIPSocket failed to decrypt header.");
|
traceEvent(TRACE_DEBUG, "readFromIPSocket failed to decrypt header.");
|
||||||
|
@ -2500,6 +2517,15 @@ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hash check (user/pw auth only)
|
||||||
|
if(eee->conf.shared_secret) {
|
||||||
|
speck_128_encrypt(hash_buf, (speck_context_t*)eee->conf.shared_secret_ctx);
|
||||||
|
if(memcmp(hash_buf, udp_buf + udp_size - N2N_REG_SUP_HASH_CHECK_LEN /* length is has already been checked */, N2N_REG_SUP_HASH_CHECK_LEN)) {
|
||||||
|
traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong hash.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(memcmp(ra.cookie, eee->curr_sn->last_cookie, N2N_COOKIE_SIZE)) {
|
if(memcmp(ra.cookie, eee->curr_sn->last_cookie, N2N_COOKIE_SIZE)) {
|
||||||
traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong or old cookie.");
|
traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong or old cookie.");
|
||||||
return;
|
return;
|
||||||
|
@ -2624,7 +2650,9 @@ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const
|
||||||
} else {
|
} else {
|
||||||
traceEvent(TRACE_ERROR, "Authentication error. MAC or IP address already in use or not released yet by supernode.");
|
traceEvent(TRACE_ERROR, "Authentication error. MAC or IP address already in use or not released yet by supernode.");
|
||||||
}
|
}
|
||||||
exit(1);
|
// REVISIT: the following portion is too harsh, repeated error warning should be sufficient until it eventually is resolved,
|
||||||
|
// preventing de-auth attacks
|
||||||
|
/* exit(1); this is too harsh, repeated error warning should be sufficient until it eventually is resolved, preventing de-auth attacks
|
||||||
} else {
|
} else {
|
||||||
HASH_FIND_PEER(eee->known_peers, nak.srcMac, peer);
|
HASH_FIND_PEER(eee->known_peers, nak.srcMac, peer);
|
||||||
if(peer != NULL) {
|
if(peer != NULL) {
|
||||||
|
@ -2633,7 +2661,7 @@ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const
|
||||||
HASH_FIND_PEER(eee->pending_peers, nak.srcMac, scan);
|
HASH_FIND_PEER(eee->pending_peers, nak.srcMac, scan);
|
||||||
if(scan != NULL) {
|
if(scan != NULL) {
|
||||||
HASH_DEL(eee->pending_peers, scan);
|
HASH_DEL(eee->pending_peers, scan);
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1240,6 +1240,8 @@ static int process_udp (n2n_sn_t * sss,
|
||||||
macstr_t mac_buf2;
|
macstr_t mac_buf2;
|
||||||
n2n_sock_str_t sockbuf;
|
n2n_sock_str_t sockbuf;
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
uint8_t hash_buf[16] = {0}; /* always size of 16 (max) despite the actual value of N2N_REG_SUP_HASH_CHECK_LEN (<= 16) */
|
||||||
|
|
||||||
struct sn_community *comm, *tmp;
|
struct sn_community *comm, *tmp;
|
||||||
uint32_t header_enc = 0; /* 1 == encrypted by static key, 2 == encrypted by dynamic key */
|
uint32_t header_enc = 0; /* 1 == encrypted by static key, 2 == encrypted by dynamic key */
|
||||||
uint64_t stamp;
|
uint64_t stamp;
|
||||||
|
@ -1289,17 +1291,20 @@ static int process_udp (n2n_sn_t * sss,
|
||||||
if(comm->header_encryption == HEADER_ENCRYPTION_NONE) {
|
if(comm->header_encryption == HEADER_ENCRYPTION_NONE) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// match with static (1) or dynamic (2) ctx?
|
// match with static (1) or dynamic (2) ctx?
|
||||||
header_enc = packet_header_decrypt(udp_buf, udp_size,
|
// check dynamic first as it is identical to static in normal header encryption mode
|
||||||
comm->community,
|
if(packet_header_decrypt(udp_buf, udp_size,
|
||||||
comm->header_encryption_ctx_static, comm->header_iv_ctx_static,
|
comm->community,
|
||||||
&stamp);
|
comm->header_encryption_ctx_dynamic, comm->header_iv_ctx_dynamic,
|
||||||
if(!header_enc)
|
&stamp)) {
|
||||||
if(packet_header_decrypt(udp_buf, udp_size,
|
|
||||||
comm->community,
|
|
||||||
comm->header_encryption_ctx_dynamic, comm->header_iv_ctx_dynamic,
|
|
||||||
&stamp))
|
|
||||||
header_enc = 2;
|
header_enc = 2;
|
||||||
|
}
|
||||||
|
if(!header_enc) {
|
||||||
|
pearson_hash_128(hash_buf, udp_buf, max(0, (int)udp_size - (int)N2N_REG_SUP_HASH_CHECK_LEN));
|
||||||
|
header_enc = packet_header_decrypt(udp_buf, max(0, (int)udp_size - (int)N2N_REG_SUP_HASH_CHECK_LEN), comm->community,
|
||||||
|
comm->header_encryption_ctx_static, comm->header_iv_ctx_static, &stamp);
|
||||||
|
}
|
||||||
|
|
||||||
if(header_enc) {
|
if(header_enc) {
|
||||||
// time stamp verification follows in the packet specific section as it requires to determine the
|
// time stamp verification follows in the packet specific section as it requires to determine the
|
||||||
|
@ -1338,6 +1343,7 @@ static int process_udp (n2n_sn_t * sss,
|
||||||
|
|
||||||
rem = udp_size; /* Counts down bytes of packet to protect against buffer overruns. */
|
rem = udp_size; /* Counts down bytes of packet to protect against buffer overruns. */
|
||||||
idx = 0; /* marches through packet header as parts are decoded. */
|
idx = 0; /* marches through packet header as parts are decoded. */
|
||||||
|
|
||||||
if(decode_common(&cmn, udp_buf, &rem, &idx) < 0) {
|
if(decode_common(&cmn, udp_buf, &rem, &idx) < 0) {
|
||||||
traceEvent(TRACE_ERROR, "Failed to decode common section");
|
traceEvent(TRACE_ERROR, "Failed to decode common section");
|
||||||
return -1; /* failed to decode packet */
|
return -1; /* failed to decode packet */
|
||||||
|
@ -1563,6 +1569,7 @@ static int process_udp (n2n_sn_t * sss,
|
||||||
int num = 0;
|
int num = 0;
|
||||||
int skip;
|
int skip;
|
||||||
int ret_value;
|
int ret_value;
|
||||||
|
sn_user_t *user = NULL;
|
||||||
|
|
||||||
memset(&ack, 0, sizeof(n2n_REGISTER_SUPER_ACK_t));
|
memset(&ack, 0, sizeof(n2n_REGISTER_SUPER_ACK_t));
|
||||||
memset(&nak, 0, sizeof(n2n_REGISTER_SUPER_NAK_t));
|
memset(&nak, 0, sizeof(n2n_REGISTER_SUPER_NAK_t));
|
||||||
|
@ -1631,6 +1638,22 @@ static int process_udp (n2n_sn_t * sss,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hash check (user/pw auth only)
|
||||||
|
if(comm->allowed_users) {
|
||||||
|
// check if submitted public key is in list of allowed users
|
||||||
|
HASH_FIND(hh, comm->allowed_users, ®.auth.token, sizeof(n2n_private_public_key_t), user);
|
||||||
|
if(user) {
|
||||||
|
speck_128_encrypt(hash_buf, (speck_context_t*)user->shared_secret_ctx);
|
||||||
|
if(memcmp(hash_buf, udp_buf + udp_size - N2N_REG_SUP_HASH_CHECK_LEN /* length has already been checked */, N2N_REG_SUP_HASH_CHECK_LEN)) {
|
||||||
|
traceEvent(TRACE_INFO, "Rx REGISTER_SUPER with wrong hash.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
traceEvent(TRACE_INFO, "Rx REGISTER_SUPER from unknown user.");
|
||||||
|
// continue and let auth check do the rest (otherwise, no NAK is sent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cmn2.ttl = N2N_DEFAULT_TTL;
|
cmn2.ttl = N2N_DEFAULT_TTL;
|
||||||
cmn2.pc = n2n_register_super_ack;
|
cmn2.pc = n2n_register_super_ack;
|
||||||
cmn2.flags = N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE;
|
cmn2.flags = N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE;
|
||||||
|
@ -1715,6 +1738,10 @@ static int process_udp (n2n_sn_t * sss,
|
||||||
packet_header_encrypt(ackbuf, encx, encx,
|
packet_header_encrypt(ackbuf, encx, encx,
|
||||||
comm->header_encryption_ctx_static, comm->header_iv_ctx_static,
|
comm->header_encryption_ctx_static, comm->header_iv_ctx_static,
|
||||||
time_stamp());
|
time_stamp());
|
||||||
|
// if user-password-auth
|
||||||
|
if(comm->allowed_users) {
|
||||||
|
encode_buf(ackbuf, &encx, hash_buf /* no matter what content */, N2N_REG_SUP_HASH_CHECK_LEN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sendto_sock(sss, socket_fd, (struct sockaddr *)sender_sock, ackbuf, encx);
|
sendto_sock(sss, socket_fd, (struct sockaddr *)sender_sock, ackbuf, encx);
|
||||||
|
|
||||||
|
@ -1753,6 +1780,14 @@ static int process_udp (n2n_sn_t * sss,
|
||||||
packet_header_encrypt(ackbuf, encx, encx,
|
packet_header_encrypt(ackbuf, encx, encx,
|
||||||
comm->header_encryption_ctx_static, comm->header_iv_ctx_static,
|
comm->header_encryption_ctx_static, comm->header_iv_ctx_static,
|
||||||
time_stamp());
|
time_stamp());
|
||||||
|
// if user-password-auth
|
||||||
|
if(comm->allowed_users) {
|
||||||
|
// append an encrypted packet hash
|
||||||
|
pearson_hash_128(hash_buf, ackbuf, encx);
|
||||||
|
// same 'user' as above
|
||||||
|
speck_128_encrypt(hash_buf, (speck_context_t*)user->shared_secret_ctx);
|
||||||
|
encode_buf(ackbuf, &encx, hash_buf, N2N_REG_SUP_HASH_CHECK_LEN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sendto_sock(sss, socket_fd, (struct sockaddr *)sender_sock, ackbuf, encx);
|
sendto_sock(sss, socket_fd, (struct sockaddr *)sender_sock, ackbuf, encx);
|
||||||
|
@ -1953,6 +1988,10 @@ static int process_udp (n2n_sn_t * sss,
|
||||||
packet_header_encrypt(nakbuf, encx, encx,
|
packet_header_encrypt(nakbuf, encx, encx,
|
||||||
comm->header_encryption_ctx_static, comm->header_iv_ctx_static,
|
comm->header_encryption_ctx_static, comm->header_iv_ctx_static,
|
||||||
time_stamp());
|
time_stamp());
|
||||||
|
// if user-password-auth
|
||||||
|
if(comm->allowed_users) {
|
||||||
|
encode_buf(nakbuf, &encx, hash_buf /* no matter what content */, N2N_REG_SUP_HASH_CHECK_LEN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sendto_peer(sss, peer, nakbuf, encx);
|
sendto_peer(sss, peer, nakbuf, encx);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user