Browse Source

Merge pull request #9 from orignal/master

Merge pull request #9 from orignal/master
pull/34/head
chertov 11 years ago
parent
commit
9f0391e3f6
  1. 4
      Queue.h
  2. 17
      README.md
  3. 83
      SSU.cpp
  4. 4
      SSU.h
  5. 101
      i2p.cpp

4
Queue.h

@ -99,6 +99,10 @@ namespace util
public: public:
MsgQueue (): m_Thread (std::bind (&MsgQueue<Msg>::Run, this)) {}; MsgQueue (): m_Thread (std::bind (&MsgQueue<Msg>::Run, this)) {};
void Stop()
{
m_Thread.detach();
}
private: private:
void Run () void Run ()

17
README.md

@ -26,14 +26,21 @@ $ ./i2p --host=YOUR_PUBLIC_IP
The client should now reseed by itself. The client should now reseed by itself.
Other options:
* --port= - The port to listen on
* --httpport= - The http port to listen on
To visit an I2P page, you need to find the b32 address of your destination. To visit an I2P page, you need to find the b32 address of your destination.
After that, go to the webconsole and add it behind the url. (Remove http:// and b32.i2p from the address) After that, go to the webconsole and add it behind the url. (Remove http:// and b32.i2p from the address)
This should resulting in for example: This should resulting in for example:
http://localhost:7070/4oes3rlgrpbkmzv4lqcfili23h3cvpwslqcfjlk6vvguxyggspwa http://localhost:7070/4oes3rlgrpbkmzv4lqcfili23h3cvpwslqcfjlk6vvguxyggspwa
Options
-------
* --host= - The external IP
* --port= - The port to listen on
* --httpport= - The http port to listen on
* --log= - Enable or disable logging to file. 1 for yes, 0 for no.
* --daemon= - Eanble or disable daemon mode. 1 for yes, 0 for no.

83
SSU.cpp

@ -55,6 +55,10 @@ namespace ssu
// session created // session created
ProcessSessionCreated (buf, len); ProcessSessionCreated (buf, len);
break; break;
case eSessionStateCreatedSent:
// session confirmed
ProcessSessionConfirmed (buf, len);
break;
default: default:
LogPrint ("SSU state not implemented yet"); LogPrint ("SSU state not implemented yet");
} }
@ -88,10 +92,33 @@ namespace ssu
{ {
m_State = eSessionStateCreatedReceived; m_State = eSessionStateCreatedReceived;
LogPrint ("Session created received"); LogPrint ("Session created received");
boost::asio::ip::address_v4 ourAddress (be32toh (*(uint32_t* )(buf + sizeof (SSUHeader) + 257))); uint8_t * ourAddress = buf + sizeof (SSUHeader) + 257;
uint16_t ourPort = be16toh (*(uint16_t *)(buf + sizeof (SSUHeader) + 261)); boost::asio::ip::address_v4 ourIP (be32toh (*(uint32_t* )(ourAddress)));
LogPrint ("Our external address is ", ourAddress.to_string (), ":", ourPort); uint16_t ourPort = be16toh (*(uint16_t *)(ourAddress + 4));
LogPrint ("Our external address is ", ourIP.to_string (), ":", ourPort);
uint32_t relayTag = be32toh (*(uint32_t *)(buf + sizeof (SSUHeader) + 263));
SendSessionConfirmed (buf + sizeof (SSUHeader), ourAddress, relayTag);
}
}
void SSUSession::ProcessSessionConfirmed (uint8_t * buf, size_t len)
{
LogPrint ("Process session confirmed");
if (Validate (buf, len, m_MacKey))
{
Decrypt (buf, len, m_SessionKey);
SSUHeader * header = (SSUHeader *)buf;
if ((header->flag >> 4) == PAYLOAD_TYPE_SESSION_CONFIRMED)
{
m_State = eSessionStateConfirmedReceived;
LogPrint ("Session confirmed received");
// TODO:
}
else
LogPrint ("Unexpected payload type ", (int)(header->flag >> 4));
} }
else
LogPrint ("MAC verifcation failed");
} }
void SSUSession::SendSessionRequest () void SSUSession::SendSessionRequest ()
@ -107,7 +134,7 @@ namespace ssu
uint8_t * payload = buf + sizeof (SSUHeader); uint8_t * payload = buf + sizeof (SSUHeader);
memcpy (payload, i2p::context.GetRouterIdentity ().publicKey, 256); memcpy (payload, i2p::context.GetRouterIdentity ().publicKey, 256);
payload[256] = 4; // we assume ipv4 payload[256] = 4; // we assume ipv4
*(uint32_t *)(payload + 257) = htobe32 (address->host.to_v4 ().to_ulong ()); *(uint32_t *)(payload + 257) = htobe32 (m_RemoteEndpoint.address ().to_v4 ().to_ulong ());
uint8_t iv[16]; uint8_t iv[16];
CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator (); CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();
@ -141,7 +168,7 @@ namespace ssu
*(uint16_t *)(payload) = htobe16 (m_RemoteEndpoint.port ()); *(uint16_t *)(payload) = htobe16 (m_RemoteEndpoint.port ());
payload += 2; payload += 2;
memcpy (signedData + 512, payload - 6, 6); // remote endpoint IP and port memcpy (signedData + 512, payload - 6, 6); // remote endpoint IP and port
*(uint32_t *)(signedData + 518) = m_Server->GetEndpoint ().address ().to_v4 ().to_ulong (); // our IP *(uint32_t *)(signedData + 518) = htobe32 (m_Server->GetEndpoint ().address ().to_v4 ().to_ulong ()); // our IP
*(uint16_t *)(signedData + 522) = htobe16 (m_Server->GetEndpoint ().port ()); // our port *(uint16_t *)(signedData + 522) = htobe16 (m_Server->GetEndpoint ().port ()); // our port
*(uint32_t *)(payload) = 0; // relay tag, always 0 for now *(uint32_t *)(payload) = 0; // relay tag, always 0 for now
payload += 4; payload += 4;
@ -164,6 +191,52 @@ namespace ssu
m_Server->Send (buf, 368, m_RemoteEndpoint); m_Server->Send (buf, 368, m_RemoteEndpoint);
} }
void SSUSession::SendSessionConfirmed (const uint8_t * y, const uint8_t * ourAddress, uint32_t relayTag)
{
auto address = m_RemoteRouter ? m_RemoteRouter->GetSSUAddress () : nullptr;
if (!address)
{
LogPrint ("Missing remote SSU address");
return;
}
uint8_t buf[480 + 18];
uint8_t * payload = buf + sizeof (SSUHeader);
*payload = 1; // 1 fragment
payload++; // info
size_t identLen = sizeof (i2p::context.GetRouterIdentity ()); // 387 bytes
*(uint16_t *)(payload) = htobe16 (identLen);
payload += 2; // cursize
memcpy (payload, (uint8_t *)&i2p::context.GetRouterIdentity (), identLen);
payload += identLen;
uint32_t signedOnTime = i2p::util::GetSecondsSinceEpoch ();
*(uint32_t *)(payload) = htobe32 (signedOnTime); // signed on time
payload += 4;
size_t paddingSize = ((payload - buf) + 40)%16;
if (paddingSize > 0) paddingSize = 16 - paddingSize;
// TODO: fill padding
payload += paddingSize; // padding size
// signature
uint8_t signedData[532]; // x,y, our IP, our port, remote IP, remote port, relayTag, our signed on time
memcpy (signedData, i2p::context.GetRouterIdentity ().publicKey, 256); // x
memcpy (signedData + 256, y, 256); // y
memcpy (signedData + 512, ourAddress, 6); // our address/port as seem by party
*(uint32_t *)(signedData + 518) = htobe32 (m_RemoteEndpoint.address ().to_v4 ().to_ulong ()); // remote IP
*(uint16_t *)(signedData + 522) = htobe16 (m_RemoteEndpoint.port ()); // remote port
*(uint32_t *)(signedData + 524) = htobe32 (relayTag); // relay tag
*(uint32_t *)(signedData + 528) = htobe32 (signedOnTime); // signed on time
i2p::context.Sign (signedData, 532, payload); // DSA signature
uint8_t iv[16];
CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();
rnd.GenerateBlock (iv, 16); // random iv
// encrypt message with session key
FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CONFIRMED, buf, 480, m_SessionKey, iv, m_MacKey);
m_State = eSessionStateConfirmedSent;
m_Server->Send (buf, 480, m_RemoteEndpoint);
}
bool SSUSession::ProcessIntroKeyEncryptedMessage (uint8_t expectedPayloadType, i2p::data::RouterInfo& r, uint8_t * buf, size_t len) bool SSUSession::ProcessIntroKeyEncryptedMessage (uint8_t expectedPayloadType, i2p::data::RouterInfo& r, uint8_t * buf, size_t len)
{ {
auto address = r.GetSSUAddress (); auto address = r.GetSSUAddress ();

4
SSU.h

@ -30,12 +30,12 @@ namespace ssu
const uint8_t PAYLOAD_TYPE_SESSION_REQUEST = 0; const uint8_t PAYLOAD_TYPE_SESSION_REQUEST = 0;
const uint8_t PAYLOAD_TYPE_SESSION_CREATED = 1; const uint8_t PAYLOAD_TYPE_SESSION_CREATED = 1;
const uint8_t PAYLOAD_TYPE_SESSION_CONFIRMED = 2; const uint8_t PAYLOAD_TYPE_SESSION_CONFIRMED = 2;
const uint8_t PAYLOAD_TYPE_SESSION_DESTROY = 8;
const uint8_t PAYLOAD_TYPE_RELAY_REQUEST = 3; const uint8_t PAYLOAD_TYPE_RELAY_REQUEST = 3;
const uint8_t PAYLOAD_TYPE_RELAY_RESPONSE = 4; const uint8_t PAYLOAD_TYPE_RELAY_RESPONSE = 4;
const uint8_t PAYLOAD_TYPE_RELAY_INTRO = 5; const uint8_t PAYLOAD_TYPE_RELAY_INTRO = 5;
const uint8_t PAYLOAD_TYPE_DATA = 6; const uint8_t PAYLOAD_TYPE_DATA = 6;
const uint8_t PAYLOAD_TYPE_TEST = 7; const uint8_t PAYLOAD_TYPE_TEST = 7;
const uint8_t PAYLOAD_TYPE_SESSION_DESTROY = 8;
enum SessionState enum SessionState
{ {
@ -69,6 +69,8 @@ namespace ssu
void SendSessionRequest (); void SendSessionRequest ();
void ProcessSessionCreated (uint8_t * buf, size_t len); void ProcessSessionCreated (uint8_t * buf, size_t len);
void SendSessionCreated (const uint8_t * x); void SendSessionCreated (const uint8_t * x);
void ProcessSessionConfirmed (uint8_t * buf, size_t len);
void SendSessionConfirmed (const uint8_t * y, const uint8_t * ourAddress, uint32_t relayTag);
bool ProcessIntroKeyEncryptedMessage (uint8_t expectedPayloadType, i2p::data::RouterInfo& r, uint8_t * buf, size_t len); bool ProcessIntroKeyEncryptedMessage (uint8_t expectedPayloadType, i2p::data::RouterInfo& r, uint8_t * buf, size_t len);
void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, uint8_t * aesKey, uint8_t * iv, uint8_t * macKey); void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, uint8_t * aesKey, uint8_t * iv, uint8_t * macKey);

101
i2p.cpp

@ -2,6 +2,13 @@
#include <thread> #include <thread>
#include <cryptopp/integer.h> #include <cryptopp/integer.h>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#ifndef _WIN32
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#endif
#include "Log.h" #include "Log.h"
#include "base64.h" #include "base64.h"
#include "Transports.h" #include "Transports.h"
@ -13,6 +20,32 @@
#include "HTTPServer.h" #include "HTTPServer.h"
#include "util.h" #include "util.h"
// Global
int running = 1;
#ifndef _WIN32
void handle_sighup(int n)
{
if (i2p::util::config::GetArg("daemon", 0) == 1)
{
static bool first=true;
if (first)
{
first=false;
return;
}
}
LogPrint("Reloading config.");
i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs);
}
void handle_shutdown(int sig)
{
running = 0; // Exit loop
}
#endif
int main( int argc, char* argv[] ) int main( int argc, char* argv[] )
{ {
i2p::util::config::OptionParser(argc,argv); i2p::util::config::OptionParser(argc,argv);
@ -23,27 +56,89 @@ int main( int argc, char* argv[] )
setlocale(LC_ALL, "Russian"); setlocale(LC_ALL, "Russian");
#endif #endif
LogPrint("\n\n\n\ni2pd starting\n"); LogPrint("\n\n\n\ni2pd starting\n");
LogPrint("data directory: ", i2p::util::filesystem::GetDataDir().string()); LogPrint("data directory: ", i2p::util::filesystem::GetDataDir().string());
i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs); i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs);
#ifndef _WIN32
struct sigaction sa;
sa.sa_handler = handle_sighup;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGHUP,&sa,0) == -1)
{
LogPrint("Failed to install SIGHUP handler.");
}
if (i2p::util::config::GetArg("-daemon", 0) == 1)
{
pid_t pid;
pid = fork();
if (pid > 0)
{
g_Log.Stop();
return 0;
}
if (pid < 0)
{
return -1;
}
umask(0);
int sid = setsid();
if (sid < 0)
{
LogPrint("Error, could not create process group.");
return -1;
}
}
// Handle shutdown
signal(SIGABRT, &handle_shutdown);
signal(SIGTERM, &handle_shutdown);
signal(SIGINT, &handle_shutdown);
#endif
if (i2p::util::config::GetArg("-log", 0) == 1)
{
std::string logfile = i2p::util::filesystem::GetDataDir().string();
#ifndef _WIN32
logfile.append("/debug.log");
#else
logfile.append("\\debug.log");
#endif
LogPrint("Logging to file enabled.");
freopen(logfile.c_str(),"a",stdout);
}
//TODO: This is an ugly workaround. fix it. //TODO: This is an ugly workaround. fix it.
//TODO: Autodetect public IP. //TODO: Autodetect public IP.
i2p::context.OverrideNTCPAddress(i2p::util::config::GetCharArg("-host", "127.0.0.1"), i2p::context.OverrideNTCPAddress(i2p::util::config::GetCharArg("-host", "127.0.0.1"),
i2p::util::config::GetArg("-port", 17070)); i2p::util::config::GetArg("-port", 17070));
int httpport = i2p::util::config::GetArg("-httpport", 7070);
i2p::util::HTTPServer httpServer (httpport); i2p::util::HTTPServer httpServer (i2p::util::config::GetArg("-httpport", 7070));
httpServer.Start (); httpServer.Start ();
i2p::data::netdb.Start (); i2p::data::netdb.Start ();
i2p::transports.Start (); i2p::transports.Start ();
i2p::tunnel::tunnels.Start (); i2p::tunnel::tunnels.Start ();
std::this_thread::sleep_for (std::chrono::seconds(10000)); while (running)
{
//TODO Meeh: Find something better to do here.
std::this_thread::sleep_for (std::chrono::seconds(1));
}
LogPrint("Shutdown started.");
i2p::tunnel::tunnels.Stop (); i2p::tunnel::tunnels.Stop ();
i2p::transports.Stop (); i2p::transports.Stop ();
i2p::data::netdb.Stop (); i2p::data::netdb.Stop ();
httpServer.Stop (); httpServer.Stop ();
if (i2p::util::config::GetArg("-log", 0) == 1)
{
fclose (stdout);
}
return 0; return 0;
} }

Loading…
Cancel
Save