2018-05-26 14:45:43 +02:00
|
|
|
/*******************************************************************************
|
|
|
|
* libretroshare/src/pgp: rscertificate.cc *
|
|
|
|
* *
|
|
|
|
* libretroshare: retroshare core library *
|
|
|
|
* *
|
2019-04-28 15:49:57 +02:00
|
|
|
* Copyright (C) 2016 Cyril Soler <csoler@users.sourceforge.net> *
|
|
|
|
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
2018-05-26 14:45:43 +02:00
|
|
|
* *
|
|
|
|
* This program is free software: you can redistribute it and/or modify *
|
2018-05-28 22:03:39 +02:00
|
|
|
* it under the terms of the GNU Lesser General Public License as *
|
2018-05-26 14:45:43 +02:00
|
|
|
* published by the Free Software Foundation, either version 3 of the *
|
|
|
|
* License, or (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
2018-05-28 22:03:39 +02:00
|
|
|
* GNU Lesser General Public License for more details. *
|
2018-05-26 14:45:43 +02:00
|
|
|
* *
|
2018-05-28 22:03:39 +02:00
|
|
|
* You should have received a copy of the GNU Lesser General Public License *
|
2018-05-26 14:45:43 +02:00
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
|
|
|
* *
|
|
|
|
*******************************************************************************/
|
2012-08-11 20:43:10 +00:00
|
|
|
#include <iostream>
|
|
|
|
#include <sstream>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2012-08-13 19:37:50 +00:00
|
|
|
#include <retroshare/rspeers.h>
|
2012-08-11 20:43:10 +00:00
|
|
|
#include <util/radix64.h>
|
|
|
|
#include <pgp/pgpkeyutil.h>
|
|
|
|
#include "rscertificate.h"
|
2014-01-18 05:27:54 +00:00
|
|
|
#include "util/rsstring.h"
|
2018-10-12 22:28:44 +02:00
|
|
|
#include "util/stacktrace.h"
|
2019-04-28 15:49:57 +02:00
|
|
|
#include "util/rsdebug.h"
|
2012-08-11 20:43:10 +00:00
|
|
|
|
2015-06-11 18:47:52 +00:00
|
|
|
//#define DEBUG_RSCERTIFICATE
|
2012-08-14 07:34:29 +00:00
|
|
|
|
2018-03-03 00:08:56 +01:00
|
|
|
static const uint8_t CERTIFICATE_VERSION_06 = 0x06;
|
|
|
|
|
|
|
|
enum CertificatePtag : uint8_t
|
|
|
|
{
|
|
|
|
CERTIFICATE_PTAG_PGP_SECTION = 0x01,
|
|
|
|
CERTIFICATE_PTAG_EXTIPANDPORT_SECTION = 0x02,
|
|
|
|
CERTIFICATE_PTAG_LOCIPANDPORT_SECTION = 0x03,
|
|
|
|
CERTIFICATE_PTAG_DNS_SECTION = 0x04,
|
|
|
|
CERTIFICATE_PTAG_SSLID_SECTION = 0x05,
|
|
|
|
CERTIFICATE_PTAG_NAME_SECTION = 0x06,
|
|
|
|
CERTIFICATE_PTAG_CHECKSUM_SECTION = 0x07,
|
|
|
|
CERTIFICATE_PTAG_HIDDENNODE_SECTION = 0x08,
|
|
|
|
CERTIFICATE_PTAG_VERSION_SECTION = 0x09,
|
|
|
|
CERTIFICATE_PTAG_EXTRA_LOCATOR = 10
|
|
|
|
};
|
2012-08-11 20:43:10 +00:00
|
|
|
|
2012-08-13 19:37:50 +00:00
|
|
|
static bool is_acceptable_radix64Char(char c)
|
2012-08-11 20:43:10 +00:00
|
|
|
{
|
2012-12-22 21:22:03 +00:00
|
|
|
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '+' || c == '/' || c == '=' ;
|
2012-08-11 20:43:10 +00:00
|
|
|
}
|
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
|
2012-08-11 20:43:10 +00:00
|
|
|
RsCertificate::~RsCertificate()
|
|
|
|
{
|
|
|
|
delete[] binary_pgp_key ;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RsCertificate::addPacket(uint8_t ptag, const unsigned char *mem, size_t size, unsigned char *& buf, size_t& offset, size_t& buf_size)
|
|
|
|
{
|
|
|
|
// Check that the buffer has sufficient size. If not, increase it.
|
|
|
|
|
|
|
|
while(offset + size + 6 >= buf_size)
|
|
|
|
{
|
|
|
|
unsigned char *newbuf = new unsigned char[2*buf_size] ;
|
|
|
|
|
|
|
|
memcpy(newbuf, buf, buf_size) ;
|
|
|
|
buf_size *= 2 ;
|
|
|
|
|
|
|
|
delete[] buf ;
|
|
|
|
|
|
|
|
buf = newbuf ;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write ptag and size
|
|
|
|
|
|
|
|
buf[offset] = ptag ;
|
|
|
|
offset += 1 ;
|
|
|
|
|
|
|
|
offset += PGPKeyParser::write_125Size(&buf[offset],size) ;
|
|
|
|
|
|
|
|
// Copy the data
|
|
|
|
|
|
|
|
memcpy(&buf[offset], mem, size) ;
|
|
|
|
offset += size ;
|
|
|
|
}
|
|
|
|
|
2018-10-12 22:28:44 +02:00
|
|
|
const RsCertificate&RsCertificate::operator=(const RsCertificate&)
|
|
|
|
{
|
|
|
|
memset(ipv4_external_ip_and_port,0,6);
|
|
|
|
memset(ipv4_internal_ip_and_port,0,6);
|
|
|
|
binary_pgp_key = nullptr;
|
|
|
|
binary_pgp_key_size = 0;
|
|
|
|
only_pgp = false;
|
|
|
|
hidden_node = false;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2012-08-11 20:43:10 +00:00
|
|
|
std::string RsCertificate::toStdString() const
|
|
|
|
{
|
2017-07-21 18:03:35 +02:00
|
|
|
//std::string res ;
|
2012-08-11 20:43:10 +00:00
|
|
|
size_t BS = 1000 ;
|
|
|
|
size_t p = 0 ;
|
|
|
|
unsigned char *buf = new unsigned char[BS] ;
|
|
|
|
|
2014-01-18 16:53:19 +00:00
|
|
|
addPacket( CERTIFICATE_PTAG_VERSION_SECTION, &CERTIFICATE_VERSION_06 , 1 , buf, p, BS ) ;
|
|
|
|
addPacket( CERTIFICATE_PTAG_PGP_SECTION , binary_pgp_key , binary_pgp_key_size , buf, p, BS ) ;
|
2012-08-15 20:08:18 +00:00
|
|
|
|
|
|
|
if(!only_pgp)
|
|
|
|
{
|
2013-09-09 02:10:49 +00:00
|
|
|
if (hidden_node)
|
|
|
|
{
|
|
|
|
addPacket( CERTIFICATE_PTAG_HIDDENNODE_SECTION, (unsigned char *)hidden_node_address.c_str(), hidden_node_address.length() , buf, p, BS ) ;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
addPacket( CERTIFICATE_PTAG_EXTIPANDPORT_SECTION, ipv4_external_ip_and_port , 6 , buf, p, BS ) ;
|
|
|
|
addPacket( CERTIFICATE_PTAG_LOCIPANDPORT_SECTION, ipv4_internal_ip_and_port , 6 , buf, p, BS ) ;
|
|
|
|
addPacket( CERTIFICATE_PTAG_DNS_SECTION , (unsigned char *)dns_name.c_str() , dns_name.length() , buf, p, BS ) ;
|
|
|
|
}
|
|
|
|
|
2012-08-15 20:08:18 +00:00
|
|
|
addPacket( CERTIFICATE_PTAG_NAME_SECTION , (unsigned char *)location_name.c_str() ,location_name.length() , buf, p, BS ) ;
|
|
|
|
addPacket( CERTIFICATE_PTAG_SSLID_SECTION , location_id.toByteArray() ,location_id.SIZE_IN_BYTES, buf, p, BS ) ;
|
2018-03-03 00:08:56 +01:00
|
|
|
|
|
|
|
for (const RsUrl& locator : mLocators)
|
|
|
|
{
|
|
|
|
std::string urlStr(locator.toString());
|
|
|
|
addPacket( CERTIFICATE_PTAG_EXTRA_LOCATOR,
|
|
|
|
(unsigned char *) urlStr.c_str(), urlStr.size(),
|
|
|
|
buf, p, BS );
|
|
|
|
}
|
2012-08-15 20:08:18 +00:00
|
|
|
}
|
2013-10-02 20:28:42 +00:00
|
|
|
|
2012-12-22 21:22:03 +00:00
|
|
|
uint32_t computed_crc = PGPKeyManagement::compute24bitsCRC(buf,p) ;
|
|
|
|
|
|
|
|
// handle endian issues.
|
|
|
|
unsigned char mem[3] ;
|
|
|
|
mem[0] = computed_crc & 0xff ;
|
|
|
|
mem[1] = (computed_crc >> 8 ) & 0xff ;
|
|
|
|
mem[2] = (computed_crc >> 16) & 0xff ;
|
2012-08-11 20:43:10 +00:00
|
|
|
|
2012-12-22 21:22:03 +00:00
|
|
|
addPacket( CERTIFICATE_PTAG_CHECKSUM_SECTION,mem,3,buf,p,BS) ;
|
2013-10-02 20:28:42 +00:00
|
|
|
|
2012-08-11 20:43:10 +00:00
|
|
|
std::string out_string ;
|
|
|
|
|
2016-05-10 22:17:48 -04:00
|
|
|
Radix64::encode(buf, p, out_string) ;
|
2012-08-11 20:43:10 +00:00
|
|
|
|
2012-08-13 19:37:50 +00:00
|
|
|
// Now slice up to 64 chars.
|
|
|
|
//
|
|
|
|
std::string out2 ;
|
|
|
|
static const int LINE_LENGTH = 64 ;
|
|
|
|
|
|
|
|
for(int i=0;i<(int)out_string.length();++i)
|
|
|
|
{
|
|
|
|
out2 += out_string[i] ;
|
|
|
|
|
|
|
|
if(i % LINE_LENGTH == LINE_LENGTH-1)
|
|
|
|
out2 += '\n' ;
|
|
|
|
}
|
|
|
|
|
2012-08-11 20:43:10 +00:00
|
|
|
delete[] buf ;
|
2012-08-13 19:37:50 +00:00
|
|
|
return out2 ;
|
2012-08-11 20:43:10 +00:00
|
|
|
}
|
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
RsCertificate::RsCertificate(const RsPeerDetails& Detail, const unsigned char *binary_pgp_block,size_t binary_pgp_block_size)
|
|
|
|
:pgp_version("Version: OpenPGP:SDK v0.9")
|
2012-08-11 20:43:10 +00:00
|
|
|
{
|
2019-04-28 15:49:57 +02:00
|
|
|
if(binary_pgp_block_size == 0 || binary_pgp_block == nullptr)
|
2018-10-12 22:28:44 +02:00
|
|
|
{
|
2019-04-28 15:49:57 +02:00
|
|
|
RsErr() << __PRETTY_FUNCTION__ << " is deprecated because it can "
|
|
|
|
<< "miserably fail like this! " << std::endl;
|
2018-10-12 22:28:44 +02:00
|
|
|
print_stacktrace();
|
2019-04-28 15:49:57 +02:00
|
|
|
throw std::runtime_error("Cannot init a certificate with a void key block.");
|
2018-10-12 22:28:44 +02:00
|
|
|
}
|
2012-08-13 19:37:50 +00:00
|
|
|
|
|
|
|
binary_pgp_key = new unsigned char[binary_pgp_block_size] ;
|
|
|
|
memcpy(binary_pgp_key,binary_pgp_block,binary_pgp_block_size) ;
|
|
|
|
binary_pgp_key_size = binary_pgp_block_size ;
|
|
|
|
|
2012-08-15 20:08:18 +00:00
|
|
|
if(!Detail.isOnlyGPGdetail)
|
|
|
|
{
|
|
|
|
only_pgp = false ;
|
2014-03-17 20:56:06 +00:00
|
|
|
location_id = RsPeerId( Detail.id ) ;
|
2012-08-15 20:08:18 +00:00
|
|
|
location_name = Detail.location ;
|
2012-08-13 19:37:50 +00:00
|
|
|
|
2013-09-09 02:10:49 +00:00
|
|
|
if (Detail.isHiddenNode)
|
|
|
|
{
|
|
|
|
hidden_node = true;
|
2014-01-18 05:27:54 +00:00
|
|
|
hidden_node_address = Detail.hiddenNodeAddress;
|
|
|
|
rs_sprintf_append(hidden_node_address, ":%u", Detail.hiddenNodePort);
|
2012-08-13 19:37:50 +00:00
|
|
|
|
2013-09-09 02:10:49 +00:00
|
|
|
memset(ipv4_internal_ip_and_port,0,6) ;
|
|
|
|
memset(ipv4_external_ip_and_port,0,6) ;
|
|
|
|
dns_name = "" ;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hidden_node = false;
|
|
|
|
hidden_node_address = "";
|
|
|
|
|
2014-01-18 05:42:44 +00:00
|
|
|
try
|
|
|
|
{
|
2018-02-25 12:48:55 +01:00
|
|
|
scan_ip(Detail.localAddr,Detail.localPort,ipv4_internal_ip_and_port);
|
2014-01-18 05:42:44 +00:00
|
|
|
}
|
|
|
|
catch(...)
|
|
|
|
{
|
2018-02-25 12:48:55 +01:00
|
|
|
std::cerr << "RsCertificate::Invalid LocalAddress: "
|
|
|
|
<< Detail.localAddr << std::endl;
|
|
|
|
memset(ipv4_internal_ip_and_port,0,6);
|
2014-01-18 05:42:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2018-02-25 12:48:55 +01:00
|
|
|
scan_ip(Detail.extAddr,Detail.extPort,ipv4_external_ip_and_port);
|
2014-01-18 05:42:44 +00:00
|
|
|
}
|
|
|
|
catch(...)
|
|
|
|
{
|
2018-02-25 12:48:55 +01:00
|
|
|
std::cerr << "RsCertificate::Invalid ExternalAddress: "
|
|
|
|
<< Detail.extAddr << std::endl;
|
2014-01-18 05:42:44 +00:00
|
|
|
memset(ipv4_external_ip_and_port,0,6) ;
|
|
|
|
}
|
2012-08-13 19:37:50 +00:00
|
|
|
|
2018-03-03 00:08:56 +01:00
|
|
|
dns_name = Detail.dyndns;
|
|
|
|
|
|
|
|
for(auto&& ipr : Detail.ipAddressList)
|
|
|
|
mLocators.insert(RsUrl(ipr.substr(0, ipr.find(' '))));
|
2013-09-09 02:10:49 +00:00
|
|
|
}
|
2012-08-15 20:08:18 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
only_pgp = true ;
|
2013-09-09 02:10:49 +00:00
|
|
|
hidden_node = false;
|
|
|
|
hidden_node_address = "";
|
2014-03-17 20:56:06 +00:00
|
|
|
location_id = RsPeerId() ;
|
2012-08-15 20:08:18 +00:00
|
|
|
location_name = "" ;
|
|
|
|
memset(ipv4_internal_ip_and_port,0,6) ;
|
|
|
|
memset(ipv4_external_ip_and_port,0,6) ;
|
|
|
|
dns_name = "" ;
|
|
|
|
}
|
2012-08-13 19:37:50 +00:00
|
|
|
}
|
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
|
|
|
|
/*static*/ std::unique_ptr<RsCertificate> RsCertificate::fromMemoryBlock(
|
|
|
|
const RsPeerDetails& details, const uint8_t* binary_pgp_block,
|
|
|
|
size_t binary_pgp_block_size )
|
|
|
|
{
|
|
|
|
if(binary_pgp_block_size == 0 || binary_pgp_block == nullptr)
|
|
|
|
{
|
|
|
|
RsErr() << __PRETTY_FUNCTION__ << " invalid parameters! " << std::endl;
|
|
|
|
print_stacktrace();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<RsCertificate> crt(new RsCertificate);
|
|
|
|
|
|
|
|
crt->binary_pgp_key = new uint8_t[binary_pgp_block_size];
|
|
|
|
memcpy(crt->binary_pgp_key, binary_pgp_block, binary_pgp_block_size);
|
|
|
|
crt->binary_pgp_key_size = binary_pgp_block_size;
|
|
|
|
|
|
|
|
if(!details.isOnlyGPGdetail)
|
|
|
|
{
|
|
|
|
crt->only_pgp = false;
|
|
|
|
crt->location_id = RsPeerId(details.id);
|
|
|
|
crt->location_name = details.location;
|
|
|
|
|
|
|
|
if (details.isHiddenNode)
|
|
|
|
{
|
|
|
|
crt->hidden_node = true;
|
|
|
|
crt->hidden_node_address = details.hiddenNodeAddress;
|
|
|
|
rs_sprintf_append(
|
|
|
|
crt->hidden_node_address, ":%u", details.hiddenNodePort);
|
|
|
|
|
|
|
|
memset(crt->ipv4_internal_ip_and_port, 0, 6);
|
|
|
|
memset(crt->ipv4_external_ip_and_port, 0, 6);
|
|
|
|
crt->dns_name = "";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
crt->hidden_node = false;
|
|
|
|
crt->hidden_node_address = "";
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
scan_ip( details.localAddr, details.localPort,
|
|
|
|
crt->ipv4_internal_ip_and_port );
|
|
|
|
}
|
|
|
|
catch(...)
|
|
|
|
{
|
|
|
|
RsErr() << __PRETTY_FUNCTION__ << " Invalid LocalAddress: "
|
|
|
|
<< details.localAddr << std::endl;
|
|
|
|
memset(crt->ipv4_internal_ip_and_port, 0, 6);
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
scan_ip( details.extAddr, details.extPort,
|
|
|
|
crt->ipv4_external_ip_and_port );
|
|
|
|
}
|
|
|
|
catch(...)
|
|
|
|
{
|
|
|
|
RsErr() << __PRETTY_FUNCTION__ << " Invalid ExternalAddress: "
|
|
|
|
<< details.extAddr << std::endl;
|
|
|
|
memset(crt->ipv4_external_ip_and_port, 0, 6);
|
|
|
|
}
|
|
|
|
|
|
|
|
crt->dns_name = details.dyndns;
|
|
|
|
|
|
|
|
for(auto&& ipr : details.ipAddressList)
|
|
|
|
crt->mLocators.insert(RsUrl(ipr.substr(0, ipr.find(' '))));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
crt->only_pgp = true;
|
|
|
|
crt->hidden_node = false;
|
|
|
|
crt->hidden_node_address = "";
|
|
|
|
crt->location_id = RsPeerId();
|
|
|
|
crt->location_name = "";
|
|
|
|
memset(crt->ipv4_internal_ip_and_port, 0, 6);
|
|
|
|
memset(crt->ipv4_external_ip_and_port, 0, 6);
|
|
|
|
crt->dns_name = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
return crt; // Implicit move semantic
|
|
|
|
}
|
|
|
|
|
2012-08-13 19:37:50 +00:00
|
|
|
void RsCertificate::scan_ip(const std::string& ip_string, unsigned short port,unsigned char *ip_and_port)
|
|
|
|
{
|
|
|
|
int d0,d1,d2,d3 ;
|
|
|
|
|
|
|
|
if(4 != sscanf(ip_string.c_str(),"%d.%d.%d.%d",&d0,&d1,&d2,&d3))
|
|
|
|
throw std::runtime_error( "Cannot parse ip from given string." );
|
|
|
|
|
|
|
|
ip_and_port[0] = d0 ;
|
|
|
|
ip_and_port[1] = d1 ;
|
|
|
|
ip_and_port[2] = d2 ;
|
|
|
|
ip_and_port[3] = d3 ;
|
|
|
|
|
|
|
|
ip_and_port[4] = (port >> 8 ) & 0xff ;
|
|
|
|
ip_and_port[5] = port & 0xff ;
|
|
|
|
}
|
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
/*static*/ std::unique_ptr<RsCertificate> RsCertificate::fromString(
|
|
|
|
const std::string& instr, uint32_t& err_code )
|
2012-08-11 20:43:10 +00:00
|
|
|
{
|
2019-04-28 15:49:57 +02:00
|
|
|
Dbg3() << __PRETTY_FUNCTION__ << std::endl;
|
|
|
|
|
|
|
|
std::unique_ptr<RsCertificate> crt(new RsCertificate);
|
|
|
|
|
|
|
|
std::string str;
|
|
|
|
err_code = CERTIFICATE_PARSING_ERROR_NO_ERROR;
|
|
|
|
|
|
|
|
// 0 - clean the string and check that it is pure radix64
|
|
|
|
for(uint32_t i=0;i<instr.length();++i)
|
2012-08-11 20:43:10 +00:00
|
|
|
{
|
2019-04-28 15:49:57 +02:00
|
|
|
if(instr[i] == ' ' || instr[i] == '\t' || instr[i] == '\n')
|
|
|
|
continue;
|
2012-08-11 20:43:10 +00:00
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
if(! is_acceptable_radix64Char(instr[i]))
|
|
|
|
return nullptr;
|
2012-08-11 20:43:10 +00:00
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
str += instr[i];
|
|
|
|
}
|
2014-01-09 20:20:46 +00:00
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
Dbg4() << __PRETTY_FUNCTION__ << " Decoding from: " << str << std::endl;
|
2012-08-11 20:43:10 +00:00
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
// 1 - decode the string.
|
2012-08-11 20:43:10 +00:00
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
std::vector<uint8_t> bf = Radix64::decode(str);
|
|
|
|
size_t size = bf.size();
|
2012-08-11 20:43:10 +00:00
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
bool checksum_check_passed = false;
|
|
|
|
unsigned char* buf = bf.data();
|
|
|
|
size_t total_s = 0;
|
|
|
|
crt->only_pgp = true;
|
|
|
|
uint8_t certificate_version = 0x00;
|
2012-08-13 19:37:50 +00:00
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
while(total_s < size)
|
|
|
|
{
|
|
|
|
uint8_t ptag = buf[0];
|
|
|
|
buf = &buf[1];
|
2014-01-09 20:20:46 +00:00
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
unsigned char *buf2 = buf;
|
2019-05-02 17:34:21 +02:00
|
|
|
uint32_t s = 0;
|
|
|
|
|
|
|
|
try { s = PGPKeyParser::read_125Size(buf); }
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR;
|
|
|
|
return nullptr;
|
|
|
|
}
|
2012-12-22 21:22:03 +00:00
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
total_s += 1 + (
|
|
|
|
reinterpret_cast<size_t>(buf) -
|
|
|
|
reinterpret_cast<size_t>(buf2) );
|
|
|
|
|
|
|
|
if(total_s > size)
|
2014-01-09 20:20:46 +00:00
|
|
|
{
|
2019-04-28 15:49:57 +02:00
|
|
|
err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR;
|
|
|
|
return nullptr;
|
2014-01-09 20:20:46 +00:00
|
|
|
}
|
2014-02-01 14:16:15 +00:00
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
Dbg3() << __PRETTY_FUNCTION__ << " Read ptag: "
|
|
|
|
<< static_cast<uint32_t>(ptag)
|
|
|
|
<< ", size " << s << ", total_s = " << total_s
|
|
|
|
<< ", expected total = " << size << std::endl;
|
|
|
|
|
|
|
|
switch(ptag)
|
2014-02-01 14:16:15 +00:00
|
|
|
{
|
2019-04-28 15:49:57 +02:00
|
|
|
case CERTIFICATE_PTAG_VERSION_SECTION:
|
|
|
|
certificate_version = buf[0];
|
|
|
|
break;
|
|
|
|
case CERTIFICATE_PTAG_PGP_SECTION:
|
|
|
|
crt->binary_pgp_key = new unsigned char[s];
|
|
|
|
memcpy(crt->binary_pgp_key, buf, s);
|
|
|
|
crt->binary_pgp_key_size = s;
|
|
|
|
break;
|
|
|
|
case CERTIFICATE_PTAG_NAME_SECTION:
|
|
|
|
crt->location_name =
|
|
|
|
std::string(reinterpret_cast<char*>(buf), s);
|
|
|
|
break;
|
|
|
|
case CERTIFICATE_PTAG_SSLID_SECTION:
|
|
|
|
if(s != crt->location_id.SIZE_IN_BYTES)
|
|
|
|
{
|
|
|
|
err_code = CERTIFICATE_PARSING_ERROR_INVALID_LOCATION_ID;
|
|
|
|
return nullptr;
|
|
|
|
}
|
2019-05-02 17:34:21 +02:00
|
|
|
// We just checked buffer size so next line is not unsafe
|
|
|
|
crt->location_id = RsPeerId::fromBufferUnsafe(buf);
|
2019-04-28 15:49:57 +02:00
|
|
|
crt->only_pgp = false;
|
|
|
|
break;
|
|
|
|
case CERTIFICATE_PTAG_DNS_SECTION:
|
|
|
|
crt->dns_name = std::string(reinterpret_cast<char*>(buf), s);
|
|
|
|
break;
|
|
|
|
case CERTIFICATE_PTAG_HIDDENNODE_SECTION:
|
|
|
|
crt->hidden_node_address =
|
|
|
|
std::string(reinterpret_cast<char*>(buf),s);
|
|
|
|
crt->hidden_node = true;
|
|
|
|
break;
|
|
|
|
case CERTIFICATE_PTAG_LOCIPANDPORT_SECTION:
|
|
|
|
if(s != 6)
|
|
|
|
{
|
|
|
|
err_code = CERTIFICATE_PARSING_ERROR_INVALID_LOCAL_IP;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
memcpy(crt->ipv4_internal_ip_and_port, buf, s);
|
|
|
|
break;
|
|
|
|
case CERTIFICATE_PTAG_EXTIPANDPORT_SECTION:
|
|
|
|
if(s != 6)
|
|
|
|
{
|
|
|
|
err_code = CERTIFICATE_PARSING_ERROR_INVALID_EXTERNAL_IP;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
memcpy(crt->ipv4_external_ip_and_port, buf, s);
|
|
|
|
break;
|
|
|
|
case CERTIFICATE_PTAG_CHECKSUM_SECTION:
|
|
|
|
{
|
|
|
|
if(s != 3 || total_s+3 != size)
|
|
|
|
{
|
|
|
|
err_code =
|
|
|
|
CERTIFICATE_PARSING_ERROR_INVALID_CHECKSUM_SECTION;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
uint32_t computed_crc =
|
|
|
|
PGPKeyManagement::compute24bitsCRC(bf.data(),size-5);
|
|
|
|
uint32_t certificate_crc = static_cast<uint32_t>(
|
|
|
|
buf[0] + (buf[1] << 8) + (buf[2] << 16) );
|
|
|
|
if(computed_crc != certificate_crc)
|
|
|
|
{
|
|
|
|
err_code = CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
else checksum_check_passed = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CERTIFICATE_PTAG_EXTRA_LOCATOR:
|
|
|
|
crt->mLocators.insert(
|
|
|
|
RsUrl(std::string(reinterpret_cast<char*>(buf), s)));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
RsWarn() << __PRETTY_FUNCTION__ << " unknwown ptag: "
|
|
|
|
<< static_cast<uint32_t>(ptag)
|
|
|
|
<< " in certificate! Ignoring it." << std::endl;
|
|
|
|
break;
|
2014-02-01 14:16:15 +00:00
|
|
|
}
|
2014-01-09 20:20:46 +00:00
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
buf = &buf[s];
|
|
|
|
total_s += s;
|
2012-08-11 20:43:10 +00:00
|
|
|
}
|
2019-04-28 15:49:57 +02:00
|
|
|
|
|
|
|
if(!checksum_check_passed)
|
2012-12-22 21:22:03 +00:00
|
|
|
{
|
2019-04-28 15:49:57 +02:00
|
|
|
err_code = CERTIFICATE_PARSING_ERROR_MISSING_CHECKSUM;
|
|
|
|
return nullptr;
|
|
|
|
}
|
2014-01-09 20:20:46 +00:00
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
if(certificate_version != CERTIFICATE_VERSION_06)
|
|
|
|
{
|
|
|
|
err_code = CERTIFICATE_PARSING_ERROR_WRONG_VERSION;
|
|
|
|
return nullptr;
|
2012-12-22 21:22:03 +00:00
|
|
|
}
|
2019-04-28 15:49:57 +02:00
|
|
|
|
|
|
|
Dbg3() << __PRETTY_FUNCTION__ << " Certificate version: "
|
|
|
|
<< static_cast<uint32_t>(certificate_version) << std::endl;
|
|
|
|
|
|
|
|
if(total_s != size)
|
|
|
|
RsWarn() << __PRETTY_FUNCTION__ << " Certificate contains trailing "
|
|
|
|
<< "characters. Weird." << std::endl;
|
|
|
|
|
|
|
|
return crt; // Implicit move semantic
|
2012-08-11 20:43:10 +00:00
|
|
|
}
|
|
|
|
|
2013-09-09 02:10:49 +00:00
|
|
|
std::string RsCertificate::hidden_node_string() const
|
|
|
|
{
|
|
|
|
if ((!only_pgp) && (hidden_node))
|
|
|
|
{
|
|
|
|
return hidden_node_address;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string empty;
|
|
|
|
return empty;
|
|
|
|
}
|
|
|
|
|
2012-08-13 19:37:50 +00:00
|
|
|
std::string RsCertificate::ext_ip_string() const
|
|
|
|
{
|
|
|
|
std::ostringstream os ;
|
|
|
|
os << (int)ipv4_external_ip_and_port[0] << "." << (int)ipv4_external_ip_and_port[1] << "." << (int)ipv4_external_ip_and_port[2] << "." << (int)ipv4_external_ip_and_port[3] ;
|
|
|
|
return os.str() ;
|
|
|
|
}
|
2019-04-28 15:49:57 +02:00
|
|
|
|
2012-08-13 19:37:50 +00:00
|
|
|
std::string RsCertificate::loc_ip_string() const
|
|
|
|
{
|
|
|
|
std::ostringstream os ;
|
|
|
|
os << (int)ipv4_internal_ip_and_port[0] << "." << (int)ipv4_internal_ip_and_port[1] << "." << (int)ipv4_internal_ip_and_port[2] << "." << (int)ipv4_internal_ip_and_port[3] ;
|
|
|
|
return os.str() ;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned short RsCertificate::ext_port_us() const
|
|
|
|
{
|
|
|
|
return (int)ipv4_external_ip_and_port[4]*256 + (int)ipv4_external_ip_and_port[5] ;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned short RsCertificate::loc_port_us() const
|
|
|
|
{
|
|
|
|
return (int)ipv4_internal_ip_and_port[4]*256 + (int)ipv4_internal_ip_and_port[5] ;
|
|
|
|
}
|
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
bool RsCertificate::cleanCertificate(
|
|
|
|
const std::string& input, std::string& output, Format& format,
|
|
|
|
int& error_code, bool check_content )
|
2012-08-13 19:37:50 +00:00
|
|
|
{
|
|
|
|
if(cleanCertificate(input,output,error_code))
|
|
|
|
{
|
2019-04-28 15:49:57 +02:00
|
|
|
format = RS_CERTIFICATE_RADIX;
|
|
|
|
if(!check_content) return true;
|
|
|
|
uint32_t errCode;
|
|
|
|
auto crt = RsCertificate::fromString(input, errCode);
|
|
|
|
error_code = static_cast<int>(errCode);
|
|
|
|
return crt != nullptr;
|
2012-08-13 19:37:50 +00:00
|
|
|
}
|
|
|
|
|
2019-04-28 15:49:57 +02:00
|
|
|
return false;
|
2012-08-13 19:37:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string RsCertificate::armouredPGPKey() const
|
|
|
|
{
|
|
|
|
return PGPKeyManagement::makeArmouredKey(binary_pgp_key,binary_pgp_key_size,pgp_version) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Yeah, this is simple, and that is what's good about the radix format. Can't be broken ;-)
|
|
|
|
//
|
|
|
|
bool RsCertificate::cleanCertificate(const std::string& instr,std::string& str,int& error_code)
|
|
|
|
{
|
|
|
|
error_code = RS_PEER_CERT_CLEANING_CODE_NO_ERROR ;
|
|
|
|
|
|
|
|
// 0 - clean the string and check that it is pure radix64
|
|
|
|
//
|
|
|
|
for(uint32_t i=0;i<instr.length();++i)
|
|
|
|
{
|
|
|
|
if(instr[i] == ' ' || instr[i] == '\t' || instr[i] == '\n')
|
|
|
|
continue ;
|
|
|
|
|
|
|
|
if(! is_acceptable_radix64Char(instr[i]))
|
|
|
|
{
|
|
|
|
error_code = RS_PEER_CERT_CLEANING_CODE_WRONG_RADIX_CHAR ;
|
|
|
|
return false ;
|
|
|
|
}
|
|
|
|
|
|
|
|
str += instr[i] ;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now slice up to 64 chars.
|
|
|
|
//
|
|
|
|
std::string str2 ;
|
|
|
|
static const int LINE_LENGTH = 64 ;
|
|
|
|
|
|
|
|
for(int i=0;i<(int)str.length();++i)
|
|
|
|
{
|
|
|
|
str2 += str[i] ;
|
|
|
|
|
|
|
|
if(i % LINE_LENGTH == LINE_LENGTH-1)
|
|
|
|
str2 += '\n' ;
|
|
|
|
}
|
|
|
|
str = str2 ;
|
|
|
|
|
|
|
|
return true ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-11 20:43:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|