Handling secio negotiation differently to comply with protocol

This commit is contained in:
jmjatlanta 2017-08-09 09:12:16 -05:00
parent 6f77a64adb
commit 4f52a20314
6 changed files with 57 additions and 45 deletions

View file

@ -50,4 +50,4 @@ int libp2p_secio_propose_protobuf_encode(struct Propose* in, unsigned char* buff
* @param out a pointer to the new struct Propose NOTE: this method allocates memory * @param out a pointer to the new struct Propose NOTE: this method allocates memory
* @returns true(1) on success, otherwise false(0) * @returns true(1) on success, otherwise false(0)
*/ */
int libp2p_secio_propose_protobuf_decode(unsigned char* buffer, size_t max_buffer_length, struct Propose** out); int libp2p_secio_propose_protobuf_decode(const unsigned char* buffer, size_t max_buffer_length, struct Propose** out);

View file

@ -21,4 +21,4 @@ struct Libp2pProtocolHandler* libp2p_secio_build_protocol_handler(struct RsaPriv
* @param remote_requested the other side is who asked for the upgrade * @param remote_requested the other side is who asked for the upgrade
* @returns true(1) on success, false(0) otherwise * @returns true(1) on success, false(0) otherwise
*/ */
int libp2p_secio_handshake(struct SessionContext* session, struct RsaPrivateKey* private_key, struct Peerstore* peerstore, int remote_requested); int libp2p_secio_handshake(struct SessionContext* session, struct RsaPrivateKey* private_key, struct Peerstore* peerstore, const uint8_t* buffer, size_t buffer_size);

View file

@ -117,7 +117,7 @@ int libp2p_peer_connect(struct RsaPrivateKey* privateKey, struct Libp2pPeer* pee
peer->sessionContext->default_stream = peer->sessionContext->insecure_stream; peer->sessionContext->default_stream = peer->sessionContext->insecure_stream;
peer->connection_type = CONNECTION_TYPE_CONNECTED; peer->connection_type = CONNECTION_TYPE_CONNECTED;
} }
libp2p_secio_handshake(peer->sessionContext, privateKey, peerstore, 0); libp2p_secio_handshake(peer->sessionContext, privateKey, peerstore, NULL, 0);
free(ip); free(ip);
} // is IP } // is IP
now = time(NULL); now = time(NULL);

View file

@ -99,7 +99,7 @@ int libp2p_secio_propose_protobuf_encode(struct Propose* in, unsigned char* buff
* @param out a pointer to the new struct Propose NOTE: this method allocates memory * @param out a pointer to the new struct Propose NOTE: this method allocates memory
* @returns true(1) on success, otherwise false(0) * @returns true(1) on success, otherwise false(0)
*/ */
int libp2p_secio_propose_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Propose** out) { int libp2p_secio_propose_protobuf_decode(const unsigned char* buffer, size_t buffer_length, struct Propose** out) {
size_t pos = 0; size_t pos = 0;
int retVal = 0, got_something = 0;; int retVal = 0, got_something = 0;;

View file

@ -50,7 +50,7 @@ int libp2p_secio_can_handle(const uint8_t* incoming, size_t incoming_size) {
int libp2p_secio_handle_message(const uint8_t* incoming, size_t incoming_size, struct SessionContext* session_context, void* protocol_context) { int libp2p_secio_handle_message(const uint8_t* incoming, size_t incoming_size, struct SessionContext* session_context, void* protocol_context) {
struct SecioContext* ctx = (struct SecioContext*)protocol_context; struct SecioContext* ctx = (struct SecioContext*)protocol_context;
return libp2p_secio_handshake(session_context, ctx->private_key, ctx->peer_store, 1); return libp2p_secio_handshake(session_context, ctx->private_key, ctx->peer_store, incoming, incoming_size);
} }
int libp2p_secio_shutdown(void* context) { int libp2p_secio_shutdown(void* context) {
@ -770,6 +770,29 @@ int libp2p_secio_encrypted_read(void* stream_context, unsigned char** bytes, siz
return retVal; return retVal;
} }
/**
* Pull the Propose struct out of what the remote node sent us
* @param buffer incoming bytes
* @param buffer_size the size of the incoming buffer
* @returns a Propose struct or NULL on error
*/
struct Propose* libp2p_secio_get_propose_in(const uint8_t* buffer, size_t buffer_size) {
struct Propose* retVal = NULL;
const uint8_t* buffer_ptr = buffer;
// strip off the protocol id
for(int i = 0; i < buffer_size; i++) {
if (buffer[i] == '\n') {
buffer_ptr = &buffer[i+1];
break;
}
}
// get the Propose struct
if (!libp2p_secio_propose_protobuf_decode(buffer_ptr, buffer_size - (buffer_ptr - buffer), &retVal)) {
return NULL;
}
return retVal;
}
/*** /***
* performs initial communication over an insecure channel to share * performs initial communication over an insecure channel to share
* keys, IDs, and initiate connection. This is a framed messaging system * keys, IDs, and initiate connection. This is a framed messaging system
@ -779,7 +802,7 @@ int libp2p_secio_encrypted_read(void* stream_context, unsigned char** bytes, siz
* @param remote_requested it is the other side that requested the upgrade to secio * @param remote_requested it is the other side that requested the upgrade to secio
* @returns true(1) on success, false(0) otherwise * @returns true(1) on success, false(0) otherwise
*/ */
int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPrivateKey* private_key, struct Peerstore* peerstore, int remote_requested) { int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPrivateKey* private_key, struct Peerstore* peerstore, const uint8_t* incoming, size_t incoming_size) {
int retVal = 0; int retVal = 0;
size_t results_size = 0, bytes_written = 0; size_t results_size = 0, bytes_written = 0;
unsigned char* propose_in_bytes = NULL; // the remote protobuf unsigned char* propose_in_bytes = NULL; // the remote protobuf
@ -804,30 +827,7 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva
//TODO: make sure we're not talking to ourself //TODO: make sure we're not talking to ourself
// prepare the multistream send of the protocol ID // send the protocol id and the outgoing Propose struct
const unsigned char* protocol = (unsigned char*)"/secio/1.0.0\n";
int protocol_len = strlen((char*)protocol);
unsigned char* total = malloc(protocol_len + propose_out_size);
memcpy(total, protocol, protocol_len);
memcpy(&total[protocol_len], propose_out_bytes, propose_out_size);
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Writing protocol\n");
bytes_written = libp2p_net_multistream_write(local_session, total, protocol_len + propose_out_size);
free(total);
if (bytes_written <= 0)
goto exit;
if (!remote_requested) {
// we should get back the secio confirmation
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Reading protocol response\n");
bytes_written = libp2p_net_multistream_read(local_session, &results, &results_size, 20);
if (bytes_written < 5 || strstr((char*)results, "secio") == NULL)
goto exit;
free(results);
results = NULL;
results_size = 0;
}
// generate 16 byte nonce // generate 16 byte nonce
if (!libp2p_secio_generate_nonce(&local_session->local_nonce[0], 16)) { if (!libp2p_secio_generate_nonce(&local_session->local_nonce[0], 16)) {
@ -868,26 +868,40 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva
// supported hashes // supported hashes
libp2p_secio_propose_set_property((void**)&propose_out->hashes, &propose_out->hashes_size, SupportedHashes, strlen(SupportedHashes)); libp2p_secio_propose_set_property((void**)&propose_out->hashes, &propose_out->hashes_size, SupportedHashes, strlen(SupportedHashes));
// send proposal // protobuf the proposal
propose_out_size = libp2p_secio_propose_protobuf_encode_size(propose_out); propose_out_size = libp2p_secio_propose_protobuf_encode_size(propose_out);
propose_out_bytes = (unsigned char*)malloc(propose_out_size); propose_out_bytes = (unsigned char*)malloc(propose_out_size);
if (libp2p_secio_propose_protobuf_encode(propose_out, propose_out_bytes, propose_out_size, &propose_out_size) == 0) if (libp2p_secio_propose_protobuf_encode(propose_out, propose_out_bytes, propose_out_size, &propose_out_size) == 0)
goto exit; goto exit;
// tack on the protocol id in front
const unsigned char* protocol = (unsigned char*)"/secio/1.0.0\n";
int protocol_len = strlen((char*)protocol);
unsigned char* total = malloc(protocol_len + propose_out_size);
memcpy(total, protocol, protocol_len);
memcpy(&total[protocol_len], propose_out_bytes, propose_out_size);
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Writing propose_out\n"); // write the Proposal to the stream
bytes_written = libp2p_secio_unencrypted_write(local_session, propose_out_bytes, propose_out_size); bytes_written = libp2p_secio_unencrypted_write(local_session, total, protocol_len + propose_out_size);
if (bytes_written < propose_out_size) if (bytes_written < propose_out_size + protocol_len)
goto exit; goto exit;
// now receive the proposal from the new connection if (incoming_size > 0) {
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "receiving propose_in\n"); propose_in_bytes = (uint8_t*)incoming;
bytes_written = libp2p_secio_unencrypted_read(local_session, &propose_in_bytes, &propose_in_size, 10); propose_in_size = incoming_size;
if (bytes_written <= 0) } else {
goto exit; bytes_written = libp2p_secio_unencrypted_read(local_session, &propose_in_bytes, &propose_in_size, 10);
if (bytes_written <= 0)
if (!libp2p_secio_propose_protobuf_decode(propose_in_bytes, propose_in_size, &propose_in)) goto exit;
}
propose_in = libp2p_secio_get_propose_in(propose_in_bytes, propose_in_size);
if (propose_in == NULL) {
libp2p_logger_error("secio", "Unable to get the remote's Propose struct\n");
if (incoming_size == 0) {
free(propose_in_bytes);
}
goto exit; goto exit;
}
// get their nonce // get their nonce
if (propose_in->rand_size != 16) if (propose_in->rand_size != 16)
@ -1102,8 +1116,6 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake complete\n"); libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake complete\n");
exit: exit:
if (propose_in_bytes != NULL)
free(propose_in_bytes);
if (propose_out_bytes != NULL) if (propose_out_bytes != NULL)
free(propose_out_bytes); free(propose_out_bytes);
if (results != NULL) if (results != NULL)

View file

@ -69,7 +69,7 @@ int test_secio_handshake() {
goto exit; goto exit;
//secure_session.host = "www.jmjatlanta.com"; //secure_session.host = "www.jmjatlanta.com";
secure_session.host = "10.211.55.2"; secure_session.host = "10.211.55.4";
secure_session.port = 4001; secure_session.port = 4001;
secure_session.traffic_type = TCP; secure_session.traffic_type = TCP;
// connect to host // connect to host
@ -80,7 +80,7 @@ int test_secio_handshake() {
goto exit; goto exit;
} }
if (!libp2p_secio_handshake(&secure_session, rsa_private_key, NULL, 0)) { if (!libp2p_secio_handshake(&secure_session, rsa_private_key, NULL, NULL, 0)) {
fprintf(stderr, "test_secio_handshake: Unable to do handshake\n"); fprintf(stderr, "test_secio_handshake: Unable to do handshake\n");
fprintf(stdout, "Shared key: "); fprintf(stdout, "Shared key: ");
for(int i = 0; i < secure_session.shared_key_size; i++) for(int i = 0; i < secure_session.shared_key_size; i++)