Beispiel #1
0
// encode packet
static int packetEncode(unsigned char *pbuf, const int pbuf_size, const struct s_packet_data *data, struct s_crypto *ctx) {
	unsigned char dec_buf[packet_CRHDR_SIZE + data->pl_buf_size];
	int32_t *scr_peerid = ((int32_t *)pbuf);
	int32_t ne_peerid;
	int len;
	
	// check if enough space is available for the operation
	if(data->pl_length > data->pl_buf_size) { return 0; }
	
	// prepare buffer
	utilWriteInt64(&dec_buf[packet_CRHDR_SEQ_START], data->seq);
	utilWriteInt16(&dec_buf[packet_CRHDR_PLLEN_START], data->pl_length);
	dec_buf[packet_CRHDR_PLTYPE_START] = data->pl_type;
	dec_buf[packet_CRHDR_PLOPT_START] = data->pl_options;
	memcpy(&dec_buf[packet_CRHDR_SIZE], data->pl_buf, data->pl_length);
	
	// encrypt buffer
	len = cryptoEnc(ctx, &pbuf[packet_PEERID_SIZE], (pbuf_size - packet_PEERID_SIZE), dec_buf, (packet_CRHDR_SIZE + data->pl_length), packet_HMAC_SIZE, packet_IV_SIZE);
	if(len < (packet_HMAC_SIZE + packet_IV_SIZE + packet_CRHDR_SIZE)) { return 0; }
	
	// write the scrambled peer ID
	utilWriteInt32((unsigned char *)&ne_peerid, data->peerid);
	scr_peerid[0] = (ne_peerid ^ (scr_peerid[1] ^ scr_peerid[2]));

	// return length of encoded packet
	return (packet_PEERID_SIZE + len);
}
Beispiel #2
0
// Generate auth message S3
static void authGenS3(struct s_auth_state *authstate) {
	// generate msg(remote_authid, msgnum, enc(keygen_nonce, local_seq, local_peerid, local_flags))
	unsigned char unencrypted_nextmsg[auth_MAXMSGSIZE_S3];
	int unencrypted_nextmsg_size = (4 + 2 + auth_NONCESIZE + seq_SIZE + 4 + 8);
	int msgnum = authstate->state;
	int encsize;
	if(authstate->local_cneg_set) {
		memcpy(unencrypted_nextmsg, authstate->remote_authid, 4);
		utilWriteInt16(&unencrypted_nextmsg[4], msgnum);
		memcpy(authstate->nextmsg, unencrypted_nextmsg, 6);
		memcpy(&unencrypted_nextmsg[(4 + 2)], authstate->local_keygen_nonce, auth_NONCESIZE);
		memcpy(&unencrypted_nextmsg[(4 + 2 + auth_NONCESIZE)], authstate->local_seq, seq_SIZE);
		utilWriteInt32(&unencrypted_nextmsg[(4 + 2 + auth_NONCESIZE + seq_SIZE)], authstate->local_peerid);
		memcpy(&unencrypted_nextmsg[(4 + 2 + auth_NONCESIZE + seq_SIZE + 4)], authstate->local_flags, 8);
		encsize = cryptoEnc(&authstate->crypto_ctx[auth_CRYPTOCTX_CNEG], &authstate->nextmsg[(4 + 2)], (auth_MAXMSGSIZE - 2 - 4), &unencrypted_nextmsg[(4 + 2)], (unencrypted_nextmsg_size - 2 - 4), auth_CNEGHMACSIZE, auth_CNEGIVSIZE);
		if(encsize > 0) {
			authstate->nextmsg_size = (encsize + 4 + 2);
		}
		else {
			authstate->nextmsg_size = 0;
		}
	}
	else {
		authstate->nextmsg_size = 0;
	}
}
Beispiel #3
0
// Get next peer manager packet. Also encapsulates packets for relaying if necessary. Returns length if successful.
static int peermgtGetNextPacket(struct s_peermgt *mgt, unsigned char *pbuf, const int pbuf_size, struct s_peeraddr *target) {
	int tnow;
	int outlen;
	int relayid;
	int relayct;
	int relaypeerid;
	int depth;
	struct s_packet_data data;
	tnow = utilGetTime();
	while((outlen = (peermgtGetNextPacketGen(mgt, pbuf, pbuf_size, tnow, target))) > 0) {
		depth = 0;
		while(outlen > 0) {
			if(depth < peermgt_DECODE_RECURSION_MAX_DEPTH) { // limit encapsulation depth
				if(!peeraddrIsInternal(target)) {
					// address is external, packet is ready for sending
					return outlen;
				}
				else {
					if(((packet_PEERID_SIZE + outlen) < peermgt_MSGSIZE_MAX) && (peeraddrGetIndirect(target, &relayid, &relayct, &relaypeerid))) {
						// address is indirect, encapsulate packet for relaying
						if(peermgtIsActiveRemoteIDCT(mgt, relayid, relayct)) {
							// generate relay-in packet
							utilWriteInt32(&mgt->relaymsgbuf[0], relaypeerid);
							memcpy(&mgt->relaymsgbuf[packet_PEERID_SIZE], pbuf, outlen);
							data.pl_buf = mgt->relaymsgbuf;
							data.pl_buf_size = packet_PEERID_SIZE + outlen;
							data.peerid = mgt->data[relayid].remoteid;
							data.seq = ++mgt->data[relayid].remoteseq;
							data.pl_length = packet_PEERID_SIZE + outlen;
							data.pl_type = packet_PLTYPE_RELAY_IN;
							data.pl_options = 0;

							// encode relay-in packet
							outlen = packetEncode(pbuf, pbuf_size, &data, &mgt->ctx[relayid]);
							if(outlen > 0) {
								mgt->data[relayid].lastsend = tnow;
								*target = mgt->data[relayid].remoteaddr;
							}
							else {
								outlen = 0;
							}
						}
						else {
							outlen = 0;
						}
					}
					else {
						outlen = 0;
					}
				}
				depth++;
			}
			else {
				outlen = 0;
			}
		}
	}
	return 0;
}
Beispiel #4
0
// Construct indirect PeerAddr.
static void peeraddrSetIndirect(struct s_peeraddr *peeraddr, const int relayid, const int relayct, const int peerid) {
	utilWriteInt32(&peeraddr->addr[0], 0);
	utilWriteInt32(&peeraddr->addr[4], peeraddr_INTERNAL_INDIRECT);
	utilWriteInt32(&peeraddr->addr[8], relayid);
	utilWriteInt32(&peeraddr->addr[12], relayct);
	utilWriteInt32(&peeraddr->addr[16], peerid);
	utilWriteInt32(&peeraddr->addr[20], 0);
}
Beispiel #5
0
// Generate peerinfo packet.
static void peermgtGenPacketPeerinfo(struct s_packet_data *data, struct s_peermgt *mgt) {
	const int peerinfo_size = (packet_PEERID_SIZE + nodeid_SIZE + peeraddr_SIZE);
	int peerinfo_max = mapGetKeyCount(&mgt->map);
	int peerinfo_count;
	int peerinfo_limit;
	int pos = 4;
	int i = 0;
	int infoid;
	unsigned char infocid[packet_PEERID_SIZE];
	struct s_nodeid infonid;

	// randomize maximum length of peerinfo packet
	if((abs(cryptoRandInt()) % 2) == 1) { peerinfo_limit = 7; } else { peerinfo_limit = 5; }

	// generate peerinfo entries
	peerinfo_count = 0;
	while((i < peerinfo_max) && (peerinfo_count < peerinfo_limit) && (pos + peerinfo_size < data->pl_buf_size)) {
		infoid = peermgtGetNextID(mgt);
		if((infoid > 0) && (mgt->data[infoid].state == peermgt_STATE_COMPLETE) && (!peeraddrIsInternal(&mgt->data[infoid].remoteaddr))) {
			utilWriteInt32(infocid, infoid);
			memcpy(&data->pl_buf[pos], infocid, packet_PEERID_SIZE);
			peermgtGetNodeID(mgt, &infonid, infoid);
			memcpy(&data->pl_buf[(pos + packet_PEERID_SIZE)], infonid.id, nodeid_SIZE);
			memcpy(&data->pl_buf[(pos + packet_PEERID_SIZE + nodeid_SIZE)], &mgt->data[infoid].remoteaddr.addr, peeraddr_SIZE);
			pos = pos + peerinfo_size;
			peerinfo_count++;
		}
		i++;
	}

	// write peerinfo_count
	utilWriteInt32(data->pl_buf, peerinfo_count);

	// set packet metadata
	data->pl_length = (4 + (peerinfo_count * peerinfo_size));
	data->pl_type = packet_PLTYPE_PEERINFO;
	data->pl_options = 0;
}
Beispiel #6
0
// Decode relay-in packet
static int peermgtDecodePacketRelayIn(struct s_peermgt *mgt, const struct s_packet_data *data) {
	int targetpeerid;
	int len = data->pl_length;
	
	if((len > 4) && (len < (peermgt_MSGSIZE_MAX - 4))) {
		targetpeerid = utilReadInt32(data->pl_buf);
		if(peermgtIsActiveRemoteID(mgt, targetpeerid)) {
			utilWriteInt32(&mgt->rrmsg.msg[0], data->peerid);
			memcpy(&mgt->rrmsg.msg[4], &data->pl_buf[4], (len - 4));
			mgt->rrmsgpeerid = targetpeerid;
			mgt->rrmsgtype = packet_PLTYPE_RELAY_OUT;
			mgt->rrmsg.len = len;
			mgt->rrmsgusetargetaddr = 0;
			return 1;
		}
	}
	
	return 0;
}
Beispiel #7
0
// Create auth state object.
static int authCreate(struct s_auth_state *authstate, struct s_netid *netid, struct s_nodekey *local_nodekey, struct s_dh_state *dhstate, const int authid) {
	utilWriteInt32(authstate->local_authid, authid);
	if(dhstate == NULL) return 0;
	if(local_nodekey == NULL) return 0;
	if(netid == NULL) return 0;
	if(!rsaIsValid(&local_nodekey->key)) return 0;
	if(!rsaIsPrivate(&local_nodekey->key)) return 0;
	
	authstate->dhstate = dhstate;
	authstate->local_nodekey = local_nodekey;
	authstate->netid = netid;
	if(nodekeyCreate(&authstate->remote_nodekey)) {
		if(cryptoCreate(authstate->crypto_ctx, auth_CRYPTOCTX_COUNT)) {
			authReset(authstate);
			return 1;
		}
		nodekeyDestroy(&authstate->remote_nodekey);
	}
	return 0;
}
Beispiel #8
0
// Generate NodeDB status report.
static void nodedbStatus(struct s_nodedb *db, char *report, const int report_len) {
	int i;
	int j;
	int size;
	int rpsize;
	int pos;
	int tnow;
	unsigned char timediff[4];
	struct s_map *addrset;
	struct s_nodedb_addrdata *addrdata;

	tnow = utilGetClock();
	size = mapGetKeyCount(db->addrdb);
	rpsize = (95 * (1 + db->num_peeraddrs)) + 2;

	pos = 0;
	memcpy(&report[pos], "NodeID + Address                                                  LastSeen  LastConn  LastTry ", 94);
	pos = pos + 94;
	report[pos++] = '\n';

	i = 0;
	while(i < size && pos < (report_len - rpsize)) {
		if(mapIsValidID(db->addrdb, i)) {
			utilByteArrayToHexstring(&report[pos], ((nodeid_SIZE * 2) + 2), mapGetKeyByID(db->addrdb, i), nodeid_SIZE);
			pos = pos + (nodeid_SIZE * 2);
			addrset = mapGetValueByID(db->addrdb, i);
			memcpy(&report[pos], "                              ", 30);
			pos = pos + 30;
			j = 0;
			while(j < db->num_peeraddrs) {
				if(mapIsValidID(addrset, j)) {
					addrdata = mapGetValueByID(addrset, j);
					report[pos++] = '\n';
					memcpy(&report[pos], "            ", 12);
					pos = pos + 12;
					report[pos++] = '-';
					report[pos++] = '-';
					report[pos++] = '>';
					report[pos++] = ' ';
					utilByteArrayToHexstring(&report[pos], ((peeraddr_SIZE * 2) + 2), mapGetKeyByID(addrset, j), peeraddr_SIZE);
					pos = pos + (peeraddr_SIZE * 2);
					report[pos++] = ' ';
					report[pos++] = ' ';
					if(addrdata->lastseen) {
						utilWriteInt32(timediff, (tnow - addrdata->lastseen_t));
						utilByteArrayToHexstring(&report[pos], 10, timediff, 4);
					}
					else {
						memcpy(&report[pos], "--------", 8);
					}
					pos = pos + 8;
					report[pos++] = ' ';
					report[pos++] = ' ';
					if(addrdata->lastconnect) {
						utilWriteInt32(timediff, (tnow - addrdata->lastconnect_t));
						utilByteArrayToHexstring(&report[pos], 10, timediff, 4);
					}
					else {
						memcpy(&report[pos], "--------", 8);
					}
					pos = pos + 8;
					report[pos++] = ' ';
					report[pos++] = ' ';
					if(addrdata->lastconntry) {
						utilWriteInt32(timediff, (tnow - addrdata->lastconntry_t));
						utilByteArrayToHexstring(&report[pos], 10, timediff, 4);
					}
					else {
						memcpy(&report[pos], "--------", 8);
					}
					pos = pos + 8;
				}
				j++;
			}
			report[pos++] = '\n';
		}
		i++;
	}
	report[pos++] = '\0';
}
Beispiel #9
0
// Generate peer manager status report.
static void peermgtStatus(struct s_peermgt *mgt, char *report, const int report_len) {
	int tnow = utilGetTime();
	int pos = 0;
	int size = mapGetMapSize(&mgt->map);
	int maxpos = (((size + 2) * (160)) + 1);
	unsigned char infoid[packet_PEERID_SIZE];
	unsigned char infostate[1];
	unsigned char infoflags[2];
	unsigned char inforq[1];
	unsigned char timediff[4];
	struct s_nodeid nodeid;
	int i = 0;
	
	if(maxpos > report_len) { maxpos = report_len; }
	
	memcpy(&report[pos], "PeerID    NodeID                                                            Address                                       Status  LastPkt   SessAge   Flag  RQ", 158);
	pos = pos + 158;
	report[pos++] = '\n';
	
	while(i < size && pos < maxpos) {
		if(peermgtGetNodeID(mgt, &nodeid, i)) {
			utilWriteInt32(infoid, i);
			utilByteArrayToHexstring(&report[pos], ((packet_PEERID_SIZE * 2) + 2), infoid, packet_PEERID_SIZE);
			pos = pos + (packet_PEERID_SIZE * 2);
			report[pos++] = ' ';
			report[pos++] = ' ';
			utilByteArrayToHexstring(&report[pos], ((nodeid_SIZE * 2) + 2), nodeid.id, nodeid_SIZE);
			pos = pos + (nodeid_SIZE * 2);
			report[pos++] = ' ';
			report[pos++] = ' ';
			utilByteArrayToHexstring(&report[pos], ((peeraddr_SIZE * 2) + 2), mgt->data[i].remoteaddr.addr, peeraddr_SIZE);
			pos = pos + (peeraddr_SIZE * 2);
			report[pos++] = ' ';
			report[pos++] = ' ';
			infostate[0] = mgt->data[i].state;
			utilByteArrayToHexstring(&report[pos], 4, infostate, 1);
			pos = pos + 2;
			report[pos++] = ' ';
			report[pos++] = ' ';
			utilWriteInt32(timediff, (tnow - mgt->data[i].lastrecv));
			utilByteArrayToHexstring(&report[pos], 10, timediff, 4);
			pos = pos + 8;
			report[pos++] = ' ';
			report[pos++] = ' ';
			utilWriteInt32(timediff, (tnow - mgt->data[i].conntime));
			utilByteArrayToHexstring(&report[pos], 10, timediff, 4);
			pos = pos + 8;
			report[pos++] = ' ';
			report[pos++] = ' ';
			utilWriteInt16(infoflags, mgt->data[i].remoteflags);
			utilByteArrayToHexstring(&report[pos], 6, infoflags, 2);
			pos = pos + 4;
			report[pos++] = ' ';
			report[pos++] = ' ';
			inforq[0] = seqRQ(&mgt->data[i].seq);
			utilByteArrayToHexstring(&report[pos], 4, inforq, 1);
			pos = pos + 2;
			report[pos++] = '\n';
		}
		i++;
	}
	report[pos++] = '\0';
}