mirror of
https://github.com/ntop/n2n.git
synced 2024-09-19 16:41:11 +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_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 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) {
|
||||
|
||||
uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0};
|
||||
uint8_t hash_buf[16] = {0};
|
||||
size_t idx;
|
||||
/* ssize_t sent; */
|
||||
n2n_common_t cmn;
|
||||
|
@ -1172,11 +1173,18 @@ void send_register_super (n2n_edge_t *eee) {
|
|||
traceEvent(TRACE_DEBUG, "send REGISTER_SUPER to %s",
|
||||
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,
|
||||
eee->conf.header_encryption_ctx_static, eee->conf.header_iv_ctx_static,
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
macstr_t mac_buf1;
|
||||
macstr_t mac_buf2;
|
||||
uint8_t hash_buf[16];
|
||||
size_t rem;
|
||||
size_t idx;
|
||||
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) {
|
||||
// match with static (1) or dynamic (2) ctx?
|
||||
header_enc = packet_header_decrypt(udp_buf, udp_size,
|
||||
(char *)eee->conf.community_name,
|
||||
eee->conf.header_encryption_ctx_static, eee->conf.header_iv_ctx_static,
|
||||
&stamp);
|
||||
if(!header_enc)
|
||||
if(packet_header_decrypt(udp_buf, udp_size,
|
||||
// check dynamic first as it is identical to static in normal header encryption mode
|
||||
if(packet_header_decrypt(udp_buf, udp_size,
|
||||
(char *)eee->conf.community_name,
|
||||
eee->conf.header_encryption_ctx_dynamic, eee->conf.header_iv_ctx_dynamic,
|
||||
&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) {
|
||||
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)) {
|
||||
traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong or old cookie.");
|
||||
return;
|
||||
|
@ -2624,7 +2650,9 @@ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const
|
|||
} else {
|
||||
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 {
|
||||
HASH_FIND_PEER(eee->known_peers, nak.srcMac, peer);
|
||||
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);
|
||||
if(scan != NULL) {
|
||||
HASH_DEL(eee->pending_peers, scan);
|
||||
}
|
||||
} */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1240,6 +1240,8 @@ static int process_udp (n2n_sn_t * sss,
|
|||
macstr_t mac_buf2;
|
||||
n2n_sock_str_t sockbuf;
|
||||
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;
|
||||
uint32_t header_enc = 0; /* 1 == encrypted by static key, 2 == encrypted by dynamic key */
|
||||
uint64_t stamp;
|
||||
|
@ -1289,17 +1291,20 @@ static int process_udp (n2n_sn_t * sss,
|
|||
if(comm->header_encryption == HEADER_ENCRYPTION_NONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// match with static (1) or dynamic (2) ctx?
|
||||
header_enc = packet_header_decrypt(udp_buf, udp_size,
|
||||
comm->community,
|
||||
comm->header_encryption_ctx_static, comm->header_iv_ctx_static,
|
||||
&stamp);
|
||||
if(!header_enc)
|
||||
if(packet_header_decrypt(udp_buf, udp_size,
|
||||
comm->community,
|
||||
comm->header_encryption_ctx_dynamic, comm->header_iv_ctx_dynamic,
|
||||
&stamp))
|
||||
// check dynamic first as it is identical to static in normal header encryption mode
|
||||
if(packet_header_decrypt(udp_buf, udp_size,
|
||||
comm->community,
|
||||
comm->header_encryption_ctx_dynamic, comm->header_iv_ctx_dynamic,
|
||||
&stamp)) {
|
||||
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) {
|
||||
// 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. */
|
||||
idx = 0; /* marches through packet header as parts are decoded. */
|
||||
|
||||
if(decode_common(&cmn, udp_buf, &rem, &idx) < 0) {
|
||||
traceEvent(TRACE_ERROR, "Failed to decode common section");
|
||||
return -1; /* failed to decode packet */
|
||||
|
@ -1563,6 +1569,7 @@ static int process_udp (n2n_sn_t * sss,
|
|||
int num = 0;
|
||||
int skip;
|
||||
int ret_value;
|
||||
sn_user_t *user = NULL;
|
||||
|
||||
memset(&ack, 0, sizeof(n2n_REGISTER_SUPER_ACK_t));
|
||||
memset(&nak, 0, sizeof(n2n_REGISTER_SUPER_NAK_t));
|
||||
|
@ -1631,6 +1638,22 @@ static int process_udp (n2n_sn_t * sss,
|
|||
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.pc = n2n_register_super_ack;
|
||||
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,
|
||||
comm->header_encryption_ctx_static, comm->header_iv_ctx_static,
|
||||
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);
|
||||
|
||||
|
@ -1753,6 +1780,14 @@ static int process_udp (n2n_sn_t * sss,
|
|||
packet_header_encrypt(ackbuf, encx, encx,
|
||||
comm->header_encryption_ctx_static, comm->header_iv_ctx_static,
|
||||
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);
|
||||
|
@ -1953,6 +1988,10 @@ static int process_udp (n2n_sn_t * sss,
|
|||
packet_header_encrypt(nakbuf, encx, encx,
|
||||
comm->header_encryption_ctx_static, comm->header_iv_ctx_static,
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue
Block a user