void NtfyPacket(std::shared_ptr<GlobalGrid::VSocket> socket,unsigned char* packetData, size_t packetLength) {
    
    if(sessions.find(socket) == sessions.end()) {
      //We should have an AES key in our packet here encrypted with our public key.
      
      
      //Packet header -- thumbprint (16 bytes) (unverified data element), session key (variable length, encrypted)
      if(packetLength<=16) {
	return;
      }
      void* packet = RSA_Decrypt(privkey,packetData+16,packetLength-16);
      if(packet == 0) { //Decryption failure.
	return;
      }
      unsigned char* buffer;
      size_t sz;
      GlobalGrid::Buffer_Get(packet,&buffer,&sz);
      if(sz>=32) {
	//We have a new Session.
	Session route(socket,buffer,packetData);
	sessions.insert(route);
	//Respond with ACK, which verifies our identity
	//Send challenge to verify remote identity.
	
	char hexprint[33];
	ToHexString((unsigned char*)route.claimedThumbprint,16,hexprint);
	hexprint[32] = 0;
	
	void* remoteKey = DB_FindAuthority(hexprint);
	
	if(remoteKey) {
	  SendChallenge(remoteKey,route,socket);
	}else {
	  //We don't have a remote key. Request it.
	  unsigned char izard[16];
	  memset(izard,0,16);
	  izard[0] = 2;
	  aes_encrypt(route.key,izard);
	  socket->Send(izard,16);
	}
	GlobalGrid::GGObject_Free(packet);
      }else {
	GlobalGrid::GGObject_Free(packet);
      }
    }else {
      //Bind to existing Session.
      if(packetLength % 16 != 0) {
	//Invalid packet.
	return;
      }
      
      Session session = *sessions.find(socket);
      for(size_t i = 0;i<packetLength;i+=16) {
	aes_decrypt(session.key,packetData+i);
      }
      
      switch(*packetData) {
	case 0:
	  //Challenge request
	{
	  //Decrypt challenge
	  uint16_t len;
	  memcpy(&len,packetData+1,2);
	  void* challenge = RSA_Decrypt(privkey,packetData+1+2,len);
	  if(challenge == 0) {
	    return;
	  }
	  unsigned char* challenge_bytes;
	  size_t challenge_sz;
	  
	  GlobalGrid::Buffer_Get(challenge,&challenge_bytes,&challenge_sz);
	  if(challenge_sz != 16) {
	    GlobalGrid::GGObject_Free(challenge);
	    return;
	  }
	  
	  unsigned char response[32];
	  memset(response,0,32);
	  response[0] = 1;
	  memcpy(response+1,challenge_bytes,16);
	  aes_encrypt(session.key,response);
	  aes_encrypt(session.key,response+16);
	  socket->Send(response,32);
	  GlobalGrid::GGObject_Free(challenge);
	  
	  
	}
	  break;
	case 1:
	{
	  //Response to challenge (identity verification)
	  if(memcmp(session.challenge,packetData+1,16) == 0) {
	    session.verified = true;
	    printf("Identity verified.\n");
	  }
	}
	  break;
	case 2:
	{
	  //Request for public encryptionKey.
	  void* key = RSA_Export(privkey,false);
	  unsigned char* key_bytes;
	  size_t key_size;
	  GlobalGrid::Buffer_Get(key,&key_bytes,&key_size);
	  size_t aligned = key_size+1;
	  aligned+=16-(aligned % 16);
	  
	  unsigned char* packet = new unsigned char[aligned];
	  memcpy(packet+1,key_bytes,key_size);
	  packet[0] = 3;
	  
	  for(size_t i = 0;i<aligned;i+=16) {
	    aes_encrypt(session.key,packet+i);
	  }
	  
	  socket->Send(packet,aligned);
	  delete[] packet;
	  GlobalGrid::GGObject_Free(key);
	  
	}
	  break;
	case 3:
	{
	  //Received public encryption key
	  void* key = RSA_Key(packetData+1,packetLength-1);
	  char thumbprint[33];
	  RSA_thumbprint(key,thumbprint);
	  thumbprint[32] = 0;
	  void* obj = DB_FindAuthority(thumbprint);
	  if(obj == 0) {
	    void* keybin = RSA_Export(key,false);
	    unsigned char* cert;
	    size_t cert_len;
	    GlobalGrid::Buffer_Get(keybin,&cert,&cert_len);
	    DB_Insert_Certificate(thumbprint,cert,cert_len,false);
	    GlobalGrid::GGObject_Free(keybin);
	    if(session.verified == false) {
	      //TODO: Send verification request
	      SendChallenge(key,session,socket);
	    }
	  }else {
	    RSA_Free(obj);
	  }
	}
	  break;
	case 4:
	{
	  //Route packet
	  packetData++;
	  unsigned char ttl = *packetData;
	  packetData++;
	  
	  //Intended destination
	  GlobalGrid::Guid dest;
	  memcpy(dest.value,packetData,16);
	  packetData+=16;
	  GlobalGrid::Guid localThumbprint;
	  RSA_thumbprint(privkey,(unsigned char*)localThumbprint.value);
	  uint32_t packetSize;
	  memcpy(&packetSize,packetData,4);
	  packetData+=16;
	  if(dest == localGuid) {
	    printf("TODO: Packet destined for ourselves\n");
	    return;
	  }
	  SendPacket(packetData,packetSize,ttl,dest,session.claimedThumbprint);
	  
	}
	  break;
      }
    }
  }
示例#2
0
int main(int argc, char** argv) {

  
  
  





void* privkey = 0;

bool(*fptr)(void*,unsigned char*,size_t);



void* thisptr = System::ABI::C([&](unsigned char* data, size_t len){
  privkey = RSA_Key(data,len);
    if(privkey == 0) {
      printf("Unable to decode private key with size %i.\n",(int)len);
      abort();
    }
    return false;
},fptr);
DB_EnumPrivateKeys(thisptr,fptr);

if(privkey == 0) {
  printf("Generating 4096-bit RSA key. This may take a while....\n");
  privkey = RSA_GenKey(4096);
  char thumbprint[33];
  thumbprint[32] = 0;
  RSA_thumbprint(privkey,thumbprint);
  unsigned char* cert;
  size_t certlen;
  void* buffy = RSA_Export(privkey,true);
  GlobalGrid::Buffer_Get(buffy,(void**)&cert,&certlen);
  printf("Generated certificate taking %i bytes\n",(int)certlen);
  DB_Insert_Certificate(thumbprint,cert,certlen,true);
  GlobalGrid::GGObject_Free(buffy);
}

if(argc>1) {
  if(strcmp(argv[1],"export") == 0) {
    //Export public key
    void* buffy = RSA_Export(privkey,false);
    unsigned char* mander;
    size_t sz;
    GlobalGrid::Buffer_Get(buffy,&mander,&sz);
    write(STDOUT_FILENO,mander,sz);
    return 0;
  }else {
    if(strcmp(argv[1],"import") == 0) {
      unsigned char mander[4096];
      
      int len = 0;
      int cl;
      while((cl = read(STDIN_FILENO,mander+len,4096-len))>0) {
	len+=cl;
	printf("Read\n");
      }
      void* key = RSA_Key(mander,len);
      if(key == 0) {
	printf("Invalid key. Cannot import.\n");
	return -1;
      }
       char thumbprint[33];
  thumbprint[32] = 0;
  RSA_thumbprint(key,thumbprint);
  DB_Insert_Certificate(thumbprint,mander,len,false);
  printf("Successfully imported key with thumbprint %s\n",thumbprint);
  
      return 0;
    }
  }
}


char thumbprint[33];
thumbprint[32] = 0;
RSA_thumbprint(privkey,thumbprint);
printf("Your private key thumbprint is %s\n",thumbprint);
void* router = GlobalGrid::GlobalGrid_InitRouter(privkey);


printf("Registering IP protocol driver with system....\n");
System::Net::IPEndpoint routerBinding;
routerBinding.ip = "::";
routerBinding.port = 0;
if(argc>1) {
  routerBinding.ip = argv[4];
  routerBinding.port = atoi(argv[5]);
}
std::shared_ptr<IPProto::IIPDriver> deriver = IPProto::CreateDriver(router,routerBinding);
GlobalGrid::GlobalGrid_RegisterProtocolDriver(router,deriver);
void* locksock = deriver->SerializeLocalSocket();

unsigned char* socket_data;
size_t sock_len;
GlobalGrid::Buffer_Get(locksock,&socket_data,&sock_len);
uint16_t portno;
memcpy(&portno,socket_data+16,2);
printf("Protocol driver active and registered (port %i)\n",(int)portno);


//TODO: Server is listening on appropriate port, as verified by netstat -l.
//Client must not be sending handshake appopriately (or server receive loop isn't working).
//Connect to specified endpoint
if(argc>1) {
  System::Net::IPEndpoint ep;
  ep.ip = argv[1];
  ep.port = atoi(argv[2]);
  const char* thumbprint = argv[3];
  //Connect to remote endpoint.
  void* key = DB_FindAuthority(thumbprint);
  if(key == 0) {
    printf("ERR: Unable to find authority figure.\n");
    abort();
  }
  GlobalGrid::GlobalGrid_InitiateHandshake(router,deriver->MakeSocket(ep),key);
  RSA_Free(key);
}


unsigned char izard[16];
memset(izard,0,16);
GlobalGrid::GlobalGrid_SendPacket(router,izard,izard,1);

    char mander[256];
auto messenger = System::MakeQueue([&](std::shared_ptr<System::Message> msg){
  unsigned char pingmsg = 0;
  GlobalGrid::Guid converted;
  FromHexString(mander,(unsigned char*)converted.value,16*2);
  GlobalGrid::GlobalGrid_SendPacket(router,converted,&pingmsg,1);
    printf("PING %s\n",mander);
});

std::thread m([&](){
  
  while(true) {
    int br = read(0,mander,256);
    if(br <=0) {
      break;
    }
    mander[br] = 0;
    messenger->Post(0);
  }
});

m.detach();


System::Enter();

return 0;
}