mirror of
https://github.com/ntop/n2n.git
synced 2024-09-19 16:41:11 +02:00
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
This commit is contained in:
parent
11661a1cbf
commit
3bd4635f04
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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);
|
||||
|
@ -1799,7 +1835,6 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
|
|||
n2n_sock_t * orig_sender=NULL;
|
||||
time_t now=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);
|
||||
|
||||
|
|
193
src/sn_utils.c
193
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),
|
||||
|
@ -386,7 +408,7 @@ static int update_edge(n2n_sn_t *sss,
|
|||
|
||||
if (NULL == scan) {
|
||||
/* Not known */
|
||||
|
||||
if(skip_add == SN_ADD){
|
||||
scan = (struct peer_info *) calloc(1,
|
||||
sizeof(struct peer_info)); /* deallocated in purge_expired_registrations */
|
||||
|
||||
|
@ -395,6 +417,8 @@ static int update_edge(n2n_sn_t *sss,
|
|||
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);
|
||||
|
@ -402,23 +426,42 @@ static int update_edge(n2n_sn_t *sss,
|
|||
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))) {
|
||||
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;
|
||||
}
|
||||
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
||||
if(scan != NULL){
|
||||
scan->last_seen = now;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -1220,10 +1263,55 @@ 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, ®, comm, &(ack.sock), now);
|
||||
if(cmn.flags & N2N_FLAGS_SOCKET){
|
||||
ret_value = update_edge(sss, ®, comm, &(ack.sock), SN_ADD_SKIP, now);
|
||||
} else {
|
||||
ret_value = update_edge(sss, ®, 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;
|
||||
|
||||
memcpy(&(nak.cookie), &(reg.cookie), sizeof(n2n_cookie_t));
|
||||
memcpy(&(nak.srcMac), &(reg.edgeMac), sizeof(n2n_mac_t));
|
||||
|
||||
encode_REGISTER_SUPER_NAK(ackbuf, &encx, &cmn2, &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));
|
||||
|
||||
sendto(sss->sock, ackbuf, encx, 0,
|
||||
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in));
|
||||
|
||||
if(cmn.flags & N2N_FLAGS_SOCKET){
|
||||
sendto_sock(sss, ®.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, ®);
|
||||
|
||||
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,
|
||||
|
@ -1236,6 +1324,8 @@ static int process_udp(n2n_sn_t * sss,
|
|||
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);
|
||||
|
@ -1243,6 +1333,45 @@ static int process_udp(n2n_sn_t * sss,
|
|||
}
|
||||
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;
|
||||
|
@ -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];
|
||||
|
|
69
src/wire.c
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…
Reference in New Issue
Block a user