Browse Source

Protection mechanism against duplicated MACs (#509)

* Prevent duplicated MACs

* Prevent duplicated MACs

* Fix compile errors

* Fix compile errors

* Implement auth scheme

* Fix compile errors

* Add auth_edge

* Add auth_edge

* Implement REGISTER_SUPER forwarding

* Add argument to update_edge

* Add auth field to supernode struct

* Add REGISTER_SUPER_NAK handling

* Fix issues

* Code clean-up

* Move auth token initialization
pull/526/head
Francesco Carli 4 years ago
committed by GitHub
parent
commit
3bd4635f04
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      include/n2n_define.h
  2. 38
      include/n2n_typedefs.h
  3. 22
      include/n2n_wire.h
  4. 95
      src/edge_utils.c
  5. 267
      src/sn_utils.c
  6. 69
      src/wire.c

13
include/n2n_define.h

@ -22,12 +22,13 @@
#define MSG_TYPE_PACKET 3
#define MSG_TYPE_REGISTER_ACK 4
#define MSG_TYPE_REGISTER_SUPER 5
#define MSG_TYPE_REGISTER_SUPER_ACK 6
#define MSG_TYPE_REGISTER_SUPER_NAK 7
#define MSG_TYPE_FEDERATION 8
#define MSG_TYPE_PEER_INFO 9
#define MSG_TYPE_QUERY_PEER 10
#define MSG_TYPE_MAX_TYPE 10
#define MSG_TYPE_UNREGISTER_SUPER 6
#define MSG_TYPE_REGISTER_SUPER_ACK 7
#define MSG_TYPE_REGISTER_SUPER_NAK 8
#define MSG_TYPE_FEDERATION 9
#define MSG_TYPE_PEER_INFO 10
#define MSG_TYPE_QUERY_PEER 11
#define MSG_TYPE_MAX_TYPE 11
/* Max available space to add supernodes' informations (sockets and MACs) in REGISTER_SUPER_ACK
* Field sizes of REGISTER_SUPER_ACK as used in encode/decode fucntions in src/wire.c

38
include/n2n_typedefs.h

@ -245,11 +245,12 @@ typedef enum n2n_pc
n2n_packet=3, /* PACKET data content */
n2n_register_ack=4, /* ACK of a registration from edge to edge */
n2n_register_super=5, /* Register edge to supernode */
n2n_register_super_ack=6, /* ACK from supernode to edge */
n2n_register_super_nak=7, /* NAK from supernode to edge - registration refused */
n2n_federation=8, /* Not used by edge */
n2n_peer_info=9, /* Send info on a peer from sn to edge */
n2n_query_peer=10 /* ask supernode for info on a peer */
n2n_unregister_super=6, /* Deregister edge from supernode */
n2n_register_super_ack=7, /* ACK from supernode to edge */
n2n_register_super_nak=8, /* NAK from supernode to edge - registration refused */
n2n_federation=9, /* Not used by edge */
n2n_peer_info=10, /* Send info on a peer from sn to edge */
n2n_query_peer=11 /* ask supernode for info on a peer */
} n2n_pc_t;
#define N2N_FLAGS_OPTIONS 0x0080
@ -289,6 +290,20 @@ typedef struct n2n_sock
} addr;
} n2n_sock_t;
typedef enum
{
n2n_auth_none = 0,
n2n_auth_simple_id = 1
} n2n_auth_scheme_t;
typedef enum
{
update_edge_no_change = 0,
update_edge_sock_change = 1,
update_edge_new_sn = 2,
update_edge_auth_fail = -1
} update_edge_ret_value_t;
typedef struct n2n_auth
{
uint16_t scheme; /* What kind of auth */
@ -338,6 +353,7 @@ typedef struct n2n_PACKET
typedef struct n2n_REGISTER_SUPER {
n2n_cookie_t cookie; /**< Link REGISTER_SUPER and REGISTER_SUPER_ACK */
n2n_mac_t edgeMac; /**< MAC to register with edge sending socket */
n2n_sock_t sock; /**< Sending socket associated with srcMac */
n2n_ip_subnet_t dev_addr; /**< IP address of the tuntap adapter. */
n2n_desc_t dev_desc; /**< Hint description correlated with the edge */
n2n_auth_t auth; /**< Authentication scheme and tokens */
@ -366,6 +382,7 @@ typedef struct n2n_REGISTER_SUPER_ACK {
typedef struct n2n_REGISTER_SUPER_NAK
{
n2n_cookie_t cookie; /* Return cookie from REGISTER_SUPER */
n2n_mac_t srcMac;
} n2n_REGISTER_SUPER_NAK_t;
@ -377,6 +394,14 @@ typedef struct n2n_REGISTER_SUPER_ACK_payload {
} n2n_REGISTER_SUPER_ACK_payload_t;
/* Linked with n2n_unregister_super in n2n_pc_t. */
typedef struct n2n_UNREGISTER_SUPER
{
n2n_auth_t auth;
n2n_mac_t srcMac;
} n2n_UNREGISTER_SUPER_t;
typedef struct n2n_PEER_INFO {
uint16_t aflags;
n2n_mac_t srcMac;
@ -401,6 +426,7 @@ struct peer_info {
n2n_desc_t dev_desc;
n2n_sock_t sock;
n2n_cookie_t last_cookie;
n2n_auth_t auth;
int timeout;
uint8_t purgeable;
time_t last_seen;
@ -546,6 +572,7 @@ typedef struct n2n_edge_conf {
int register_ttl; /**< TTL for registration packet when UDP NAT hole punching through supernode. */
int local_port;
int mgmt_port;
n2n_auth_t auth;
filter_rule_t *network_traffic_filter_rules;
} n2n_edge_conf_t;
@ -660,6 +687,7 @@ typedef struct n2n_sn
struct sn_community *communities;
struct sn_community_regular_expression *rules;
struct sn_community *federation;
n2n_auth_t auth;
} n2n_sn_t;

22
include/n2n_wire.h

@ -131,6 +131,17 @@ int decode_REGISTER_SUPER( n2n_REGISTER_SUPER_t * pkt,
size_t * rem,
size_t * idx );
int encode_UNREGISTER_SUPER(uint8_t *base,
size_t *idx,
const n2n_common_t *common,
const n2n_UNREGISTER_SUPER_t *unreg);
int decode_UNREGISTER_SUPER(n2n_UNREGISTER_SUPER_t *unreg,
const n2n_common_t *cmn, /* info on how to interpret it */
const uint8_t *base,
size_t *rem,
size_t *idx);
int encode_REGISTER_ACK( uint8_t * base,
size_t * idx,
const n2n_common_t * common,
@ -155,6 +166,17 @@ int decode_REGISTER_SUPER_ACK( n2n_REGISTER_SUPER_ACK_t * reg,
size_t * idx,
uint8_t * tmpbuf);
int encode_REGISTER_SUPER_NAK( uint8_t * base,
size_t * idx,
const n2n_common_t * cmn,
const n2n_REGISTER_SUPER_NAK_t * nak);
int decode_REGISTER_SUPER_NAK( n2n_REGISTER_SUPER_NAK_t * nak,
const n2n_common_t * cmn, /* info on how to interpret it */
const uint8_t * base,
size_t * rem,
size_t * idx);
int fill_sockaddr( struct sockaddr * addr,
size_t addrlen,
const n2n_sock_t * sock );

95
src/edge_utils.c

@ -179,6 +179,7 @@ n2n_edge_t* edge_init(const n2n_edge_conf_t *conf, int *rv) {
n2n_edge_t *eee = calloc(1, sizeof(n2n_edge_t));
int rc = -1, i = 0;
struct peer_info *scan, *tmp;
size_t idx = 0;
if((rc = edge_verify_conf(conf)) != 0) {
traceEvent(TRACE_ERROR, "Invalid configuration");
@ -259,6 +260,14 @@ n2n_edge_t* edge_init(const n2n_edge_conf_t *conf, int *rv) {
// if called in-between, see "Supernode not responding" in update_supernode_reg(...)
eee->udp_sock = -1;
eee->udp_mgmt_sock = -1;
eee->conf.auth.scheme = n2n_auth_simple_id;
for (idx = 0; idx < N2N_AUTH_TOKEN_SIZE; ++idx)
eee->conf.auth.token[idx] = n2n_rand() % 0xff;
eee->conf.auth.toksize = sizeof(eee->conf.auth.token);
#ifndef SKIP_MULTICAST_PEERS_DISCOVERY
eee->udp_multicast_sock = -1;
#endif
@ -773,7 +782,7 @@ static void send_register_super(n2n_edge_t *eee) {
reg.dev_addr.net_addr = ntohl(eee->device.ip_addr);
reg.dev_addr.net_bitlen = mask2bitlen(ntohl(eee->device.device_mask));
memcpy(reg.dev_desc, eee->conf.dev_desc, N2N_DESC_SIZE);
reg.auth.scheme = 0; /* No auth yet */
memcpy(&(reg.auth), &(eee->conf.auth), sizeof(n2n_auth_t));
idx = 0;
encode_mac(reg.edgeMac, &idx, eee->device.mac_addr);
@ -793,10 +802,49 @@ static void send_register_super(n2n_edge_t *eee) {
}
static void send_unregister_super(n2n_edge_t *eee){
uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0};
size_t idx;
/* ssize_t sent; */
n2n_common_t cmn;
n2n_UNREGISTER_SUPER_t unreg;
n2n_sock_str_t sockbuf;
memset(&cmn, 0, sizeof(cmn));
memset(&unreg, 0, sizeof(unreg));
cmn.ttl = N2N_DEFAULT_TTL;
cmn.pc = n2n_unregister_super;
cmn.flags = 0;
memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE);
memcpy(&(unreg.auth), &(eee->conf.auth), sizeof(n2n_auth_t));
idx = 0;
encode_mac(unreg.srcMac, &idx, eee->device.mac_addr);
idx = 0;
encode_UNREGISTER_SUPER(pktbuf, &idx, &cmn, &unreg);
traceEvent(TRACE_DEBUG, "send UNREGISTER_SUPER to %s",
sock_to_cstr(sockbuf, &(eee->curr_sn->sock)));
if (eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED)
packet_header_encrypt(pktbuf, idx, eee->conf.header_encryption_ctx,
eee->conf.header_iv_ctx,
time_stamp(), pearson_hash_16(pktbuf, idx));
/* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, &(eee->curr_sn->sock));
}
static int sort_supernodes(n2n_edge_t *eee, time_t now){
struct peer_info *scan, *tmp;
if(eee->curr_sn != eee->conf.supernodes){
send_unregister_super(eee);
eee->curr_sn = eee->conf.supernodes;
memcpy(&eee->supernode, &(eee->curr_sn->sock), sizeof(n2n_sock_t));
eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS;
@ -1027,18 +1075,6 @@ void update_supernode_reg(n2n_edge_t * eee, time_t nowTime) {
/* ************************************** */
/** NOT IMPLEMENTED
*
* This would send a DEREGISTER packet to a peer edge or supernode to indicate
* the edge is going away.
*/
static void send_deregister(n2n_edge_t * eee,
n2n_sock_t * remote_peer) {
/* Marshall and send message */
}
/* ************************************** */
/** Return the IP address of the current supernode in the ring. */
static const char * supernode_ip(const n2n_edge_t * eee) {
return (eee->curr_sn->ip_addr);
@ -1798,8 +1834,7 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
n2n_sock_t sender;
n2n_sock_t * orig_sender=NULL;
time_t now=0;
uint64_t stamp = 0;
uint64_t stamp = 0;
size_t i;
i = sizeof(sender_sock);
@ -2107,6 +2142,33 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
}
break;
}
case MSG_TYPE_REGISTER_SUPER_NAK: {
n2n_REGISTER_SUPER_NAK_t nak;
struct peer_info *peer, *scan;
memset(&nak, 0, sizeof(n2n_REGISTER_SUPER_NAK_t));
decode_REGISTER_SUPER_NAK(&nak, &cmn, udp_buf, &rem, &idx);
traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_NAK");
if((memcmp(&(nak.srcMac), &(eee->device.mac_addr), sizeof(n2n_mac_t))) == 0){
traceEvent(TRACE_ERROR, "%s is already used. Stopping the program.", macaddr_str(mac_buf1, nak.srcMac));
exit(1);
} else {
HASH_FIND_PEER(eee->known_peers, nak.srcMac, peer);
if(peer != NULL){
HASH_DEL(eee->known_peers, peer);
}
HASH_FIND_PEER(eee->pending_peers, nak.srcMac, scan);
if(scan != NULL){
HASH_DEL(eee->pending_peers, scan);
}
}
break;
}
case MSG_TYPE_PEER_INFO: {
n2n_PEER_INFO_t pi;
struct peer_info * scan;
@ -2314,7 +2376,7 @@ int run_edge_loop(n2n_edge_t * eee, int *keep_running) {
WaitForSingleObject(tun_read_thread, INFINITE);
#endif
send_deregister(eee, &(eee->supernode));
send_unregister_super(eee);
closesocket(eee->udp_sock);
@ -2325,6 +2387,7 @@ int run_edge_loop(n2n_edge_t * eee, int *keep_running) {
/** Deinitialise the edge and deallocate any owned memory. */
void edge_term(n2n_edge_t * eee) {
if(eee->udp_sock >= 0)
closesocket(eee->udp_sock);

267
src/sn_utils.c

@ -52,6 +52,7 @@ static int update_edge(n2n_sn_t *sss,
const n2n_REGISTER_SUPER_t* reg,
struct sn_community *comm,
const n2n_sock_t *sender_sock,
int skip_add,
time_t now);
static int purge_expired_communities(n2n_sn_t *sss,
@ -258,6 +259,7 @@ int comm_init(struct sn_community *comm, char *cmn) {
/** Initialise the supernode structure */
int sn_init(n2n_sn_t *sss) {
int i;
size_t idx;
#ifdef WIN32
initWin32();
@ -296,6 +298,14 @@ int sn_init(n2n_sn_t *sss) {
n2n_srand (n2n_seed());
/* Random auth token */
sss->auth.scheme = n2n_auth_simple_id;
for (idx = 0; idx < N2N_AUTH_TOKEN_SIZE; ++idx)
sss->auth.token[idx] = n2n_rand() % 0xff;
sss->auth.toksize = sizeof(sss->auth.token);
/* Random MAC address */
for(i=0; i<6; i++) {
sss->mac_addr[i] = n2n_rand();
@ -354,16 +364,28 @@ static uint16_t reg_lifetime(n2n_sn_t *sss)
return 15;
}
/** Compare two authentication tokens. It is called by update_edge
* and in UNREGISTER_SUPER handling to compare the stored auth token
* with the one received from the packet.
*/
static int auth_edge(const n2n_auth_t *auth1, const n2n_auth_t *auth2){
/* 0 = success (tokens are equal). */
return (memcmp(auth1, auth2, sizeof(n2n_auth_t)));
}
/** Update the edge table with the details of the edge which contacted the
* supernode. */
static int update_edge(n2n_sn_t *sss,
const n2n_REGISTER_SUPER_t* reg,
struct sn_community *comm,
const n2n_sock_t *sender_sock,
int skip_add,
time_t now) {
macstr_t mac_buf;
n2n_sock_str_t sockbuf;
struct peer_info *scan, *iter, *tmp;
int auth;
int ret;
traceEvent(TRACE_DEBUG, "update_edge for %s [%s]",
macaddr_str(mac_buf, reg->edgeMac),
@ -385,40 +407,61 @@ static int update_edge(n2n_sn_t *sss,
}
if (NULL == scan) {
/* Not known */
scan = (struct peer_info *) calloc(1,
/* Not known */
if(skip_add == SN_ADD){
scan = (struct peer_info *) calloc(1,
sizeof(struct peer_info)); /* deallocated in purge_expired_registrations */
memcpy(&(scan->mac_addr), reg->edgeMac, sizeof(n2n_mac_t));
scan->dev_addr.net_addr = reg->dev_addr.net_addr;
scan->dev_addr.net_bitlen = reg->dev_addr.net_bitlen;
memcpy((char*)scan->dev_desc, reg->dev_desc, N2N_DESC_SIZE);
memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t));
scan->last_valid_time_stamp = initial_time_stamp();
memcpy(&(scan->mac_addr), reg->edgeMac, sizeof(n2n_mac_t));
scan->dev_addr.net_addr = reg->dev_addr.net_addr;
scan->dev_addr.net_bitlen = reg->dev_addr.net_bitlen;
memcpy((char*)scan->dev_desc, reg->dev_desc, N2N_DESC_SIZE);
memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t));
memcpy(&(scan->last_cookie), reg->cookie, sizeof(N2N_COOKIE_SIZE));
memcpy(&(scan->auth), &(reg->auth), sizeof(n2n_auth_t));
scan->last_valid_time_stamp = initial_time_stamp();
HASH_ADD_PEER(comm->edges, scan);
HASH_ADD_PEER(comm->edges, scan);
traceEvent(TRACE_INFO, "update_edge created %s ==> %s",
macaddr_str(mac_buf, reg->edgeMac),
sock_to_cstr(sockbuf, sender_sock));
}
traceEvent(TRACE_INFO, "update_edge created %s ==> %s",
macaddr_str(mac_buf, reg->edgeMac),
sock_to_cstr(sockbuf, sender_sock));
ret = update_edge_new_sn;
} else {
/* Known */
if (!sock_equal(sender_sock, &(scan->sock))) {
memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t));
if((auth = auth_edge(&(scan->auth), &(reg->auth))) == 0){
memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t));
memcpy(&(scan->last_cookie), reg->cookie, sizeof(N2N_COOKIE_SIZE));
traceEvent(TRACE_INFO, "update_edge updated %s ==> %s",
macaddr_str(mac_buf, reg->edgeMac),
sock_to_cstr(sockbuf, sender_sock));
ret = update_edge_sock_change;
} else {
traceEvent(TRACE_INFO, "authentication failed");
ret = update_edge_auth_fail;
}
traceEvent(TRACE_INFO, "update_edge updated %s ==> %s",
macaddr_str(mac_buf, reg->edgeMac),
sock_to_cstr(sockbuf, sender_sock));
} else {
memcpy(&(scan->last_cookie), reg->cookie, sizeof(N2N_COOKIE_SIZE));
traceEvent(TRACE_DEBUG, "update_edge unchanged %s ==> %s",
macaddr_str(mac_buf, reg->edgeMac),
sock_to_cstr(sockbuf, sender_sock));
ret = update_edge_no_change;
}
}
scan->last_seen = now;
return 0;
if(scan != NULL){
scan->last_seen = now;
}
return ret;
}
@ -602,7 +645,7 @@ static int re_register_and_purge_supernodes(n2n_sn_t *sss, struct sn_community *
memcpy(reg.cookie, cookie, N2N_COOKIE_SIZE);
reg.dev_addr.net_addr = ntohl(peer->dev_addr.net_addr);
reg.dev_addr.net_bitlen = mask2bitlen(ntohl(peer->dev_addr.net_bitlen));
reg.auth.scheme = 0; /* No auth yet */
memcpy(&(reg.auth), &(sss->auth), sizeof(n2n_auth_t));
idx = 0;
encode_mac(reg.edgeMac, &idx, sss->mac_addr);
@ -812,7 +855,7 @@ static int process_udp(n2n_sn_t * sss,
n2n_sock_str_t sockbuf;
char buf[32];
struct sn_community *comm, *tmp;
uint64_t stamp;
uint64_t stamp;
const n2n_mac_t null_mac = {0, 0, 0, 0, 0, 0}; /* 00:00:00:00:00:00 */
traceEvent(TRACE_DEBUG, "Processing incoming UDP packet [len: %lu][sender: %s:%u]",
@ -1073,8 +1116,11 @@ static int process_udp(n2n_sn_t * sss,
{
n2n_REGISTER_SUPER_t reg;
n2n_REGISTER_SUPER_ACK_t ack;
n2n_REGISTER_SUPER_NAK_t nak;
n2n_common_t cmn2;
uint8_t ackbuf[N2N_SN_PKTBUF_SIZE];
uint8_t tmpbuf[REG_SUPER_ACK_PAYLOAD_SPACE];
uint8_t *tmp_dst;
uint8_t payload_buf[REG_SUPER_ACK_PAYLOAD_SPACE];
n2n_REGISTER_SUPER_ACK_payload_t *payload;
size_t encx=0;
@ -1088,8 +1134,10 @@ static int process_udp(n2n_sn_t * sss,
int num = 0;
int skip_add;
int skip;
int ret_value;
memset(&ack, 0, sizeof(n2n_REGISTER_SUPER_ACK_t));
memset(&nak, 0, sizeof(n2n_REGISTER_SUPER_NAK_t));
/* Edge/supernode requesting registration with us. */
sss->stats.last_reg_super=now;
@ -1118,7 +1166,7 @@ static int process_udp(n2n_sn_t * sss,
if( (allowed_match != -1)
&& (match_length == strlen((const char *)cmn.community)) // --- only full matches allowed (remove, if also partial matches wanted)
&& (allowed_match == 0)) { // --- only full matches allowed (remove, if also partial matches wanted)
&& (allowed_match == 0)) { // --- only full matches allowed (remove, if also partial matches wanted)
match = 1;
break;
}
@ -1175,11 +1223,6 @@ static int process_udp(n2n_sn_t * sss,
ack.sock.port = ntohs(sender_sock->sin_port);
memcpy(ack.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE);
if((from_supernode == 0) != (comm->is_federation == IS_NO_FEDERATION)) {
traceEvent(TRACE_DEBUG, "process_udp dropped REGISTER_SUPER: from_supernode value doesn't correspond to the internal federation marking");
return -1;
}
/* Add sender's data to federation (or update it) */
if(comm->is_federation == IS_FEDERATION) {
skip_add = SN_ADD;
@ -1191,7 +1234,7 @@ static int process_udp(n2n_sn_t * sss,
/* Skip random numbers of supernodes before payload assembling, calculating an appropriate random_number.
* That way, all supernodes have a chance to be propagated with REGISTER_SUPER_ACK. */
skip = HASH_COUNT(sss->federation->edges) - (int)(REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE / REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE);
skip = (skip < 0) ? 0 : n2n_rand_sqr(skip);
skip = (skip < 0) ? 0 : n2n_rand_sqr(skip);
/* Assembling supernode list for REGISTER_SUPER_ACK payload */
payload = (n2n_REGISTER_SUPER_ACK_payload_t*)payload_buf;
@ -1220,44 +1263,130 @@ static int process_udp(n2n_sn_t * sss,
sock_to_cstr(sockbuf, &(ack.sock)));
if(memcmp(reg.edgeMac, &null_mac, N2N_MAC_SIZE) != 0) {
update_edge(sss, &reg, comm, &(ack.sock), now);
if(cmn.flags & N2N_FLAGS_SOCKET){
ret_value = update_edge(sss, &reg, comm, &(ack.sock), SN_ADD_SKIP, now);
} else {
ret_value = update_edge(sss, &reg, comm, &(ack.sock), SN_ADD, now);
}
}
encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack, payload_buf);
if(ret_value == update_edge_auth_fail){
cmn2.pc = n2n_register_super_nak;
if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED)
packet_header_encrypt (ackbuf, encx, comm->header_encryption_ctx,
comm->header_iv_ctx,
time_stamp (), pearson_hash_16 (ackbuf, encx));
memcpy(&(nak.cookie), &(reg.cookie), sizeof(n2n_cookie_t));
memcpy(&(nak.srcMac), &(reg.edgeMac), sizeof(n2n_mac_t));
sendto(sss->sock, ackbuf, encx, 0,
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in));
encode_REGISTER_SUPER_NAK(ackbuf, &encx, &cmn2, &nak);
traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]",
macaddr_str(mac_buf, reg.edgeMac),
sock_to_cstr(sockbuf, &(ack.sock)));
if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED)
packet_header_encrypt (ackbuf, encx, comm->header_encryption_ctx,
comm->header_iv_ctx,
time_stamp (), pearson_hash_16 (ackbuf, encx));
sendto(sss->sock, ackbuf, encx, 0,
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in));
if(cmn.flags & N2N_FLAGS_SOCKET){
sendto_sock(sss, &reg.sock, ackbuf, encx);
}
traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_NAK for %s",
macaddr_str(mac_buf, reg.edgeMac));
} else {
if(!(cmn.flags & N2N_FLAGS_SOCKET)){
reg.sock.family = AF_INET;
reg.sock.port = ntohs(sender_sock->sin_port);
memcpy(reg.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE);
cmn2.pc = n2n_register_super;
encode_REGISTER_SUPER(ackbuf, &encx, &cmn2, &reg);
if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED)
packet_header_encrypt (ackbuf, encx, comm->header_encryption_ctx,
comm->header_iv_ctx,
time_stamp (), pearson_hash_16 (ackbuf, encx));
try_broadcast(sss, NULL, &cmn, reg.edgeMac, from_supernode, ackbuf, encx);
encx = 0;
cmn2.pc = n2n_register_super_ack;
encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack, tmpbuf);
if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED)
packet_header_encrypt (ackbuf, encx, comm->header_encryption_ctx,
comm->header_iv_ctx,
time_stamp (), pearson_hash_16 (ackbuf, encx));
sendto(sss->sock, ackbuf, encx, 0,
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in));
traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]",
macaddr_str(mac_buf, reg.edgeMac),
sock_to_cstr(sockbuf, &(ack.sock)));
}
}
} else {
traceEvent(TRACE_INFO, "Discarded registration: unallowed community '%s'",
(char*)cmn.community);
return -1;
}
break;
}
case MSG_TYPE_UNREGISTER_SUPER: {
n2n_UNREGISTER_SUPER_t unreg;
struct peer_info *peer;
int auth;
memset(&unreg, 0, sizeof(n2n_UNREGISTER_SUPER_t));
if(!comm) {
traceEvent(TRACE_DEBUG, "process_udp UNREGISTER_SUPER with unknown community %s", cmn.community);
return -1;
}
if((from_supernode == 0) != (comm->is_federation == IS_NO_FEDERATION)) {
traceEvent(TRACE_DEBUG, "process_udp dropped UNREGISTER_SUPER: from_supernode value doesn't correspond to the internal federation marking.");
return -1;
}
decode_UNREGISTER_SUPER(&unreg, &cmn, udp_buf, &rem, &idx);
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) {
if(!find_edge_time_stamp_and_verify (comm->edges, from_supernode, unreg.srcMac, stamp, TIME_STAMP_NO_JITTER)) {
traceEvent(TRACE_DEBUG, "process_udp dropped UNREGISTER_SUPER due to time stamp error.");
return -1;
}
}
traceEvent(TRACE_DEBUG, "Rx UNREGISTER_SUPER from %s",
macaddr_str(mac_buf, unreg.srcMac));
HASH_FIND_PEER(comm->edges, unreg.srcMac, peer);
if(peer != NULL){
if((auth = auth_edge(&(peer->auth), &unreg.auth)) == 0){
HASH_DEL(comm->edges, peer);
}
}
break;
}
case MSG_TYPE_REGISTER_SUPER_ACK: {
n2n_REGISTER_SUPER_ACK_t ack;
size_t encx=0;
struct sn_community *fed;
n2n_REGISTER_SUPER_ACK_t ack;
size_t encx=0;
struct sn_community *fed;
struct peer_info *scan, *tmp;
n2n_sock_str_t sockbuf1;
n2n_sock_str_t sockbuf2;
macstr_t mac_buf1;
macstr_t mac_buf1;
n2n_sock_t sender;
n2n_sock_t *orig_sender;
n2n_sock_t *tmp_sock;
n2n_mac_t *tmp_mac;
int i;
int i;
uint8_t dec_tmpbuf[REG_SUPER_ACK_PAYLOAD_SPACE];
int skip_add;
int skip_add;
n2n_REGISTER_SUPER_ACK_payload_t *payload;
memset(&sender, 0, sizeof(n2n_sock_t));
@ -1322,6 +1451,50 @@ static int process_udp(n2n_sn_t * sss,
break;
}
case MSG_TYPE_REGISTER_SUPER_NAK: {
n2n_REGISTER_SUPER_NAK_t nak;
size_t encx=0;
struct peer_info *peer;
n2n_sock_str_t sockbuf;
macstr_t mac_buf;
n2n_sock_t sender;
memset(&sender, 0, sizeof(n2n_sock_t));
sender.family = AF_INET;
sender.port = ntohs(sender_sock->sin_port);
memcpy(&(sender.addr.v4), &(sender_sock->sin_addr.s_addr), IPV4_SIZE);
memset(&nak, 0, sizeof(n2n_REGISTER_SUPER_NAK_t));
if(!comm) {
traceEvent(TRACE_DEBUG, "process_udp REGISTER_SUPER_NAK with unknown community %s", cmn.community);
return -1;
}
decode_REGISTER_SUPER_NAK(&nak, &cmn, udp_buf, &rem, &idx);
if (comm) {
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) {
if(!find_edge_time_stamp_and_verify (comm->edges, from_supernode, nak.srcMac, stamp, TIME_STAMP_NO_JITTER)) {
traceEvent(TRACE_DEBUG, "process_udp dropped REGISTER_SUPER_NAK due to time stamp error.");
return -1;
}
}
}
traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_NAK from %s [%s]",
macaddr_str(mac_buf, nak.srcMac),
sock_to_cstr(sockbuf, &sender));
HASH_FIND_PEER(comm->edges, nak.srcMac, peer);
if(comm->is_federation == IS_NO_FEDERATION){
if(peer != NULL){
HASH_DEL(comm->edges, peer);
}
}
break;
}
case MSG_TYPE_QUERY_PEER: {
n2n_QUERY_PEER_t query;
uint8_t encbuf[N2N_SN_PKTBUF_SIZE];
@ -1329,10 +1502,10 @@ static int process_udp(n2n_sn_t * sss,
n2n_common_t cmn2;
n2n_PEER_INFO_t pi;
struct sn_community_regular_expression *re, *tmp_re;
struct peer_info *peer, *tmp_peer, *p;
struct peer_info *peer, *tmp_peer, *p;
int8_t allowed_match = -1;
uint8_t match = 0;
int match_length = 0;
int match_length = 0;
uint8_t *rec_buf; /* either udp_buf or encbuf */
if(!comm && sss->lock_communities) {

69
src/wire.c

@ -324,11 +324,15 @@ int encode_REGISTER_SUPER(uint8_t *base,
retval += encode_common(base, idx, common);
retval += encode_buf(base, idx, reg->cookie, N2N_COOKIE_SIZE);
retval += encode_mac(base, idx, reg->edgeMac);
if (0 != reg->sock.family) {
retval += encode_sock(base, idx, &(reg->sock));
}
retval += encode_uint32(base, idx, reg->dev_addr.net_addr);
retval += encode_uint8(base, idx, reg->dev_addr.net_bitlen);
retval += encode_buf(base, idx, reg->dev_desc, N2N_DESC_SIZE);
retval += encode_uint16(base, idx, 0); /* NULL auth scheme */
retval += encode_uint16(base, idx, 0); /* No auth data */
retval += encode_uint16(base, idx, reg->auth.scheme);
retval += encode_uint16(base, idx, reg->auth.toksize);
retval += encode_buf(base, idx, reg->auth.token, reg->auth.toksize);
return retval;
}
@ -343,6 +347,9 @@ int decode_REGISTER_SUPER(n2n_REGISTER_SUPER_t *reg,
memset(reg, 0, sizeof(n2n_REGISTER_SUPER_t));
retval += decode_buf(reg->cookie, N2N_COOKIE_SIZE, base, rem, idx);
retval += decode_mac(reg->edgeMac, base, rem, idx);
if (cmn->flags & N2N_FLAGS_SOCKET) {
retval += decode_sock(&(reg->sock), base, rem, idx);
}
retval += decode_uint32(&(reg->dev_addr.net_addr), base, rem, idx);
retval += decode_uint8(&(reg->dev_addr.net_bitlen), base, rem, idx);
retval += decode_buf(reg->dev_desc, N2N_DESC_SIZE, base, rem, idx);
@ -353,6 +360,37 @@ int decode_REGISTER_SUPER(n2n_REGISTER_SUPER_t *reg,
}
int encode_UNREGISTER_SUPER(uint8_t *base,
size_t *idx,
const n2n_common_t *common,
const n2n_UNREGISTER_SUPER_t *unreg){
int retval = 0;
retval += encode_common(base, idx, common);
retval += encode_uint16(base, idx, unreg->auth.scheme);
retval += encode_uint16(base, idx, unreg->auth.toksize);
retval += encode_buf(base, idx, unreg->auth.token, unreg->auth.toksize);
retval += encode_mac(base, idx, unreg->srcMac);
return retval;
}
int decode_UNREGISTER_SUPER(n2n_UNREGISTER_SUPER_t *unreg,
const n2n_common_t *cmn, /* info on how to interpret it */
const uint8_t *base,
size_t *rem,
size_t *idx){
size_t retval = 0;
memset(unreg, 0, sizeof(n2n_UNREGISTER_SUPER_t));
retval += decode_uint16(&(unreg->auth.scheme), base, rem, idx);
retval += decode_uint16(&(unreg->auth.toksize), base, rem, idx);
retval += decode_buf(unreg->auth.token, unreg->auth.toksize, base, rem, idx);
retval += decode_mac(unreg->srcMac, base, rem, idx);
return retval;
}
int encode_REGISTER_ACK(uint8_t *base,
size_t *idx,
const n2n_common_t *common,
@ -442,6 +480,33 @@ int decode_REGISTER_SUPER_ACK(n2n_REGISTER_SUPER_ACK_t *reg,
}
int encode_REGISTER_SUPER_NAK(uint8_t *base,
size_t *idx,
const n2n_common_t *common,
const n2n_REGISTER_SUPER_NAK_t *nak) {
int retval = 0;
retval += encode_common(base, idx, common);
retval += encode_buf(base, idx, nak->cookie, N2N_COOKIE_SIZE);
retval += encode_mac(base, idx, nak->srcMac);
return retval;
}
int decode_REGISTER_SUPER_NAK(n2n_REGISTER_SUPER_NAK_t *nak,
const n2n_common_t *cmn, /* info on how to interpret it */
const uint8_t *base,
size_t *rem,
size_t *idx) {
size_t retval = 0;
memset(nak, 0, sizeof(n2n_REGISTER_SUPER_NAK_t));
retval += decode_buf(nak->cookie, N2N_COOKIE_SIZE, base, rem, idx);
retval += decode_mac(nak->srcMac, base, rem, idx);
return retval;
}
int fill_sockaddr( struct sockaddr * addr,
size_t addrlen,
const n2n_sock_t * sock )

Loading…
Cancel
Save