Beispiel #1
0
// decode packet
static int packetDecode(struct s_packet_data *data, const unsigned char *pbuf, const int pbuf_size, struct s_crypto *ctx, struct s_seq_state *seqstate) {
	unsigned char dec_buf[pbuf_size];
	int len;

	// decrypt packet
	if(pbuf_size < (packet_PEERID_SIZE + packet_HMAC_SIZE + packet_IV_SIZE)) { return 0; }
	len = cryptoDec(ctx, dec_buf, pbuf_size, &pbuf[packet_PEERID_SIZE], (pbuf_size - packet_PEERID_SIZE), packet_HMAC_SIZE, packet_IV_SIZE);
	if(len < packet_CRHDR_SIZE) { return 0; };

	// get packet data
	data->peerid = packetGetPeerID(pbuf);
	data->seq = utilReadInt64(&dec_buf[packet_CRHDR_SEQ_START]);
	if(seqstate != NULL) if(!seqVerify(seqstate, data->seq)) { return 0; }
	data->pl_options = dec_buf[packet_CRHDR_PLOPT_START];
	data->pl_type = dec_buf[packet_CRHDR_PLTYPE_START];
	data->pl_length = utilReadInt16(&dec_buf[packet_CRHDR_PLLEN_START]);
	if(!(data->pl_length > 0)) {
		data->pl_length = 0;
		return 0;
	}
	if(len < (packet_CRHDR_SIZE + data->pl_length)) { return 0; }
	if(data->pl_length > data->pl_buf_size) { return 0; }
	memcpy(data->pl_buf, &dec_buf[packet_CRHDR_SIZE], data->pl_length);

	// return length of decoded payload
	return (data->pl_length);
}
Beispiel #2
0
// Decode input packet recursively. Decapsulates relayed packets if necessary.
static int peermgtDecodePacketRecursive(struct s_peermgt *mgt, const unsigned char *packet, const int packet_len, const struct s_peeraddr *source_addr, const int tnow, const int depth) {
	int ret;
	int peerid;
	struct s_packet_data data = { .pl_buf_size = peermgt_MSGSIZE_MAX, .pl_buf = mgt->msgbuf };
	struct s_peeraddr indirect_addr;
	ret = 0;
	if(packet_len > (packet_PEERID_SIZE + packet_HMAC_SIZE) && (depth < peermgt_DECODE_RECURSION_MAX_DEPTH)) {
		peerid = packetGetPeerID(packet);
		if(peermgtIsActiveID(mgt, peerid)) {
			if(peerid > 0) {
				// packet has an active PeerID
				mgt->msgsize = 0;
				if(packetDecode(&data, packet, packet_len, &mgt->ctx[peerid], &mgt->data[peerid].seq) > 0) {
					if((data.pl_length > 0) && (data.pl_length < peermgt_MSGSIZE_MAX)) {
						switch(data.pl_type) {
							case packet_PLTYPE_USERDATA:
								if(peermgtGetFlag(mgt, peermgt_FLAG_USERDATA)) {
									ret = 1;
									mgt->msgsize = data.pl_length;
									mgt->msgpeerid = data.peerid;
								}
								else {
									ret = 0;
								}
								break;
							case packet_PLTYPE_USERDATA_FRAGMENT:
								if(peermgtGetFlag(mgt, peermgt_FLAG_USERDATA)) {
									ret = peermgtDecodeUserdataFragment(mgt, &data);
									if(ret > 0) {
										mgt->msgsize = data.pl_length;
										mgt->msgpeerid = data.peerid;
									}
								}
								else {
									ret = 0;
								}
								break;
							case packet_PLTYPE_PEERINFO:
								ret = peermgtDecodePacketPeerinfo(mgt, &data);
								break;
							case packet_PLTYPE_PING:
								ret = peermgtDecodePacketPing(mgt, &data);
								break;
							case packet_PLTYPE_PONG:
								ret = peermgtDecodePacketPong(mgt, &data);
								break;
							case packet_PLTYPE_RELAY_IN:
								if(peermgtGetFlag(mgt, peermgt_FLAG_RELAY)) {
									ret = peermgtDecodePacketRelayIn(mgt, &data);
								}
								else {
									ret = 0;
								}
								break;
							case packet_PLTYPE_RELAY_OUT:
								if(data.pl_length > packet_PEERID_SIZE) {
									memcpy(mgt->relaymsgbuf, &data.pl_buf[4], (data.pl_length - packet_PEERID_SIZE)); 
									peeraddrSetIndirect(&indirect_addr, peerid, mgt->data[peerid].conntime, utilReadInt32(&data.pl_buf[0])); // generate indirect PeerAddr
									ret = peermgtDecodePacketRecursive(mgt, mgt->relaymsgbuf, (data.pl_length - packet_PEERID_SIZE), &indirect_addr, tnow, (depth + 1)); // decode decapsulated packet
								}
								break;
							default:
								ret = 0;
								break;
						}
						if(ret > 0) {
							mgt->data[peerid].lastrecv = tnow;
							mgt->data[peerid].remoteaddr = *source_addr;
							return 1;
						}
					}
				}
			}
			else if(peerid == 0) {
				// packet has an anonymous PeerID
				if(packetDecode(&data, packet, packet_len, &mgt->ctx[0], NULL)) {
					switch(data.pl_type) {
						case packet_PLTYPE_AUTH:
							return peermgtDecodePacketAuth(mgt, &data, source_addr);
						default:
							return 0;
					}
				}
			}
		}
	}
	return 0;
}


// Decode input packet. Returns 1 on success.
static int peermgtDecodePacket(struct s_peermgt *mgt, const unsigned char *packet, const int packet_len, const struct s_peeraddr *source_addr) {
	int tnow;
	tnow = utilGetTime();
	return peermgtDecodePacketRecursive(mgt, packet, packet_len, source_addr, tnow, 0);
}