From 4f52a20314f4f6fb35af58a449350ab05810a3cf Mon Sep 17 00:00:00 2001 From: jmjatlanta Date: Wed, 9 Aug 2017 09:12:16 -0500 Subject: [PATCH] Handling secio negotiation differently to comply with protocol --- include/libp2p/secio/propose.h | 2 +- include/libp2p/secio/secio.h | 2 +- peer/peer.c | 2 +- secio/propose.c | 2 +- secio/secio.c | 90 +++++++++++++++++++--------------- test/test_secio.h | 4 +- 6 files changed, 57 insertions(+), 45 deletions(-) diff --git a/include/libp2p/secio/propose.h b/include/libp2p/secio/propose.h index c47bea9..4007d06 100644 --- a/include/libp2p/secio/propose.h +++ b/include/libp2p/secio/propose.h @@ -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 * @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); diff --git a/include/libp2p/secio/secio.h b/include/libp2p/secio/secio.h index 9240d4d..5f4fb7c 100644 --- a/include/libp2p/secio/secio.h +++ b/include/libp2p/secio/secio.h @@ -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 * @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); diff --git a/peer/peer.c b/peer/peer.c index aa87d49..3f1cf65 100644 --- a/peer/peer.c +++ b/peer/peer.c @@ -117,7 +117,7 @@ int libp2p_peer_connect(struct RsaPrivateKey* privateKey, struct Libp2pPeer* pee peer->sessionContext->default_stream = peer->sessionContext->insecure_stream; 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); } // is IP now = time(NULL); diff --git a/secio/propose.c b/secio/propose.c index 2ee1520..fc49b85 100644 --- a/secio/propose.c +++ b/secio/propose.c @@ -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 * @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; int retVal = 0, got_something = 0;; diff --git a/secio/secio.c b/secio/secio.c index 239a0b0..2f3985e 100644 --- a/secio/secio.c +++ b/secio/secio.c @@ -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) { 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) { @@ -770,6 +770,29 @@ int libp2p_secio_encrypted_read(void* stream_context, unsigned char** bytes, siz 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 * 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 * @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; size_t results_size = 0, bytes_written = 0; 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 - // prepare the multistream send of the protocol ID - 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; - } + // send the protocol id and the outgoing Propose struct // generate 16 byte nonce 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 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_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) 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"); - bytes_written = libp2p_secio_unencrypted_write(local_session, propose_out_bytes, propose_out_size); - if (bytes_written < propose_out_size) + // write the Proposal to the stream + bytes_written = libp2p_secio_unencrypted_write(local_session, total, protocol_len + propose_out_size); + if (bytes_written < propose_out_size + protocol_len) goto exit; - // now receive the proposal from the new connection - libp2p_logger_log("secio", LOGLEVEL_DEBUG, "receiving propose_in\n"); - bytes_written = libp2p_secio_unencrypted_read(local_session, &propose_in_bytes, &propose_in_size, 10); - if (bytes_written <= 0) - goto exit; - - if (!libp2p_secio_propose_protobuf_decode(propose_in_bytes, propose_in_size, &propose_in)) + if (incoming_size > 0) { + propose_in_bytes = (uint8_t*)incoming; + propose_in_size = incoming_size; + } else { + bytes_written = libp2p_secio_unencrypted_read(local_session, &propose_in_bytes, &propose_in_size, 10); + if (bytes_written <= 0) + 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; + } // get their nonce 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"); exit: - if (propose_in_bytes != NULL) - free(propose_in_bytes); if (propose_out_bytes != NULL) free(propose_out_bytes); if (results != NULL) diff --git a/test/test_secio.h b/test/test_secio.h index af7bb02..565c928 100644 --- a/test/test_secio.h +++ b/test/test_secio.h @@ -69,7 +69,7 @@ int test_secio_handshake() { goto exit; //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.traffic_type = TCP; // connect to host @@ -80,7 +80,7 @@ int test_secio_handshake() { 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(stdout, "Shared key: "); for(int i = 0; i < secure_session.shared_key_size; i++)