From 9e5934acc82c1b58da6c7f8e2633d4cc445c4790 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Sun, 26 Apr 2020 15:46:41 +0200 Subject: [PATCH 01/15] added ChaCha20 (cc20) --- Makefile.in | 2 +- edge_utils.c | 6 + n2n.h | 3 + n2n_transforms.h | 1 + tools/benchmark.c | 12 ++ transform_cc20.c | 293 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 316 insertions(+), 1 deletion(-) create mode 100644 transform_cc20.c diff --git a/Makefile.in b/Makefile.in index 14f5599..d428259 100644 --- a/Makefile.in +++ b/Makefile.in @@ -50,7 +50,7 @@ MAN8DIR=$(MANDIR)/man8 N2N_LIB=libn2n.a N2N_OBJS=n2n.o wire.o minilzo.o twofish.o \ edge_utils.o sn_utils.o \ - transform_null.o transform_tf.o transform_aes.o \ + transform_null.o transform_tf.o transform_aes.o transform_cc20.o \ tuntap_freebsd.o tuntap_netbsd.o tuntap_linux.o \ tuntap_osx.o LIBS_EDGE+=$(LIBS_EDGE_OPT) diff --git a/edge_utils.c b/edge_utils.c index acae39e..9376503 100644 --- a/edge_utils.c +++ b/edge_utils.c @@ -138,6 +138,7 @@ static const char* transop_str(enum n2n_transform tr) { case N2N_TRANSFORM_ID_NULL: return("null"); case N2N_TRANSFORM_ID_TWOFISH: return("twofish"); case N2N_TRANSFORM_ID_AESCBC: return("AES-CBC"); + case N2N_TRANSFORM_ID_CHACHA20:return("ChaCha20"); default: return("invalid"); }; } @@ -240,6 +241,11 @@ n2n_edge_t* edge_init(const tuntap_dev *dev, const n2n_edge_conf_t *conf, int *r case N2N_TRANSFORM_ID_AESCBC: rc = n2n_transop_aes_cbc_init(&eee->conf, &eee->transop); break; +#endif +#ifdef HAVE_OPENSSL_1_1 + case N2N_TRANSFORM_ID_CHACHA20: + rc = n2n_transop_cc20_init(&eee->conf, &eee->transop); + break; #endif default: rc = n2n_transop_null_init(&eee->conf, &eee->transop); diff --git a/n2n.h b/n2n.h index dbdb5a3..5c23480 100644 --- a/n2n.h +++ b/n2n.h @@ -293,6 +293,9 @@ int n2n_transop_twofish_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); #ifdef N2N_HAVE_AES int n2n_transop_aes_cbc_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); #endif +#ifdef HAVE_OPENSSL_1_1 +int n2n_transop_cc20_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); +#endif /* Log */ void setTraceLevel(int level); diff --git a/n2n_transforms.h b/n2n_transforms.h index 1ede8cf..f203257 100644 --- a/n2n_transforms.h +++ b/n2n_transforms.h @@ -30,6 +30,7 @@ typedef enum n2n_transform { N2N_TRANSFORM_ID_NULL = 1, N2N_TRANSFORM_ID_TWOFISH = 2, N2N_TRANSFORM_ID_AESCBC = 3, + N2N_TRANSFORM_ID_CHACHA20 = 4, } n2n_transform_t; struct n2n_trans_op; diff --git a/tools/benchmark.c b/tools/benchmark.c index 381f511..9197035 100644 --- a/tools/benchmark.c +++ b/tools/benchmark.c @@ -96,6 +96,9 @@ int main(int argc, char * argv[]) { n2n_trans_op_t transop_null, transop_twofish; #ifdef N2N_HAVE_AES n2n_trans_op_t transop_aes_cbc; +#endif +#ifdef HAVE_OPENSSL_1_1 + n2n_trans_op_t transop_cc20; #endif n2n_edge_conf_t conf; @@ -112,6 +115,9 @@ int main(int argc, char * argv[]) { #ifdef N2N_HAVE_AES n2n_transop_aes_cbc_init(&conf, &transop_aes_cbc); #endif +#ifdef HAVE_OPENSSL_1_1 + n2n_transop_cc20_init(&conf, &transop_cc20); +#endif /* Run the tests */ run_transop_benchmark("transop_null", &transop_null, &conf, pktbuf); @@ -119,6 +125,9 @@ int main(int argc, char * argv[]) { #ifdef N2N_HAVE_AES run_transop_benchmark("transop_aes", &transop_aes_cbc, &conf, pktbuf); #endif +#ifdef N2N_HAVE_AES + run_transop_benchmark("transop_cc20", &transop_cc20, &conf, pktbuf); +#endif /* Cleanup */ transop_null.deinit(&transop_null); @@ -126,6 +135,9 @@ int main(int argc, char * argv[]) { #ifdef N2N_HAVE_AES transop_aes_cbc.deinit(&transop_aes_cbc); #endif +#ifdef HAVE_OPENSSL_1_1 + transop_cc20.deinit(&transop_cc20); +#endif return 0; } diff --git a/transform_cc20.c b/transform_cc20.c new file mode 100644 index 0000000..d6e2ee1 --- /dev/null +++ b/transform_cc20.c @@ -0,0 +1,293 @@ +/** + * (C) 2007-20 - ntop.org and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ + +#include "n2n.h" +#include "n2n_transforms.h" + +#ifdef HAVE_OPENSSL_1_1 + +#include +#include +#include + +#define N2N_CC20_TRANSFORM_VERSION 1 /* version of the transform encoding */ +#define N2N_CC20_IVEC_SIZE 16 + +#define CC20_KEY_BYTES (256/8) + +/* ChaCha20 plaintext preamble */ +#define TRANSOP_CC20_VER_SIZE 1 /* Support minor variants in encoding in one module. */ +#define TRANSOP_CC20_PREAMBLE_SIZE (TRANSOP_CC20_VER_SIZE + N2N_CC20_IVEC_SIZE) + +typedef unsigned char n2n_cc20_ivec_t[N2N_CC20_IVEC_SIZE]; + +typedef struct transop_cc20 { + EVP_CIPHER_CTX *enc_ctx; /* openssl's reusable evp_* encryption context */ + EVP_CIPHER_CTX *dec_ctx; /* openssl's reusable evp_* decryption context */ + const EVP_CIPHER *cipher; /* cipher to use: EVP_chacha20() */ + uint8_t key[32]; /* the pure key data for payload encryption & decryption */ +} transop_cc20_t; + +/* ****************************************************** */ + +static int transop_deinit_cc20(n2n_trans_op_t *arg) { + transop_cc20_t *priv = (transop_cc20_t *)arg->priv; + + EVP_CIPHER_CTX_free(priv->enc_ctx); + EVP_CIPHER_CTX_free(priv->dec_ctx); + + if(priv) + free(priv); + + return 0; +} + +/* ****************************************************** */ + +/* get any erorr message out of openssl + taken from https://en.wikibooks.org/wiki/OpenSSL/Error_handling */ +char *openssl_err_as_string (void) { + BIO *bio = BIO_new (BIO_s_mem ()); + ERR_print_errors (bio); + char *buf = NULL; + size_t len = BIO_get_mem_data (bio, &buf); + char *ret = (char *) calloc (1, 1 + len); + + if(ret) + memcpy (ret, buf, len); + + BIO_free (bio); + return ret; +} + +/* ****************************************************** */ + +static void set_cc20_iv(transop_cc20_t *priv, n2n_cc20_ivec_t ivec) { + // keep in mind the following condition: N2N_CC20_IVEC_SIZE % sizeof(rand_value) == 0 ! + uint32_t rand_value; + for (uint8_t i = 0; i < N2N_CC20_IVEC_SIZE; i += sizeof(rand_value)) { + rand_value = rand(); // CONCERN: rand() is not consideren cryptographicly secure, REPLACE later + memcpy(ivec + i, &rand_value, sizeof(rand_value)); + } +} + +/* ****************************************************** */ + +/** The ChaCha20 packet format consists of: + * + * - a 8-bit cc20 encoding version in clear text + * - a 128-bit random IV + * - encrypted payload. + * + * [V|IIII|DDDDDDDDDDDDDDDDDDDDD] + * |<---- encrypted ---->| + */ +static int transop_encode_cc20(n2n_trans_op_t * arg, + uint8_t * outbuf, + size_t out_len, + const uint8_t * inbuf, + size_t in_len, + const uint8_t * peer_mac) { + int len=-1; + transop_cc20_t * priv = (transop_cc20_t *)arg->priv; + uint8_t assembly[N2N_PKT_BUF_SIZE] = {0}; + + if(in_len <= N2N_PKT_BUF_SIZE) { + if((in_len + TRANSOP_CC20_PREAMBLE_SIZE) <= out_len) { + size_t idx=0; + n2n_cc20_ivec_t enc_ivec = {0}; + + traceEvent(TRACE_DEBUG, "encode_cc20 %lu", in_len); + + /* Encode the ChaCha20 format version. */ + encode_uint8(outbuf, &idx, N2N_CC20_TRANSFORM_VERSION); + + /* Generate and encode the IV. */ + set_cc20_iv(priv, enc_ivec); + encode_buf(outbuf, &idx, &enc_ivec, N2N_CC20_IVEC_SIZE); + + /* Encrypt the assembly contents and write the ciphertext after the iv. */ + /* len is set to the length of the cipher plain text to be encrpyted + which is (in this case) identical to original packet lentgh */ + len = in_len; + + /* The assembly buffer is a source for encrypting data. + * The whole contents of assembly are encrypted. */ + memcpy(assembly, inbuf, in_len); + + EVP_CIPHER_CTX *ctx = priv->enc_ctx; + int evp_len; + int evp_ciphertext_len; + + if(1 == EVP_EncryptInit_ex(ctx, priv->cipher, NULL, priv->key, enc_ivec)) { + if(1 == EVP_CIPHER_CTX_set_padding(ctx, 0)) { + if(1 == EVP_EncryptUpdate(ctx, outbuf + TRANSOP_CC20_PREAMBLE_SIZE, &evp_len, assembly, len)) { + evp_ciphertext_len = evp_len; + if(1 == EVP_EncryptFinal_ex(ctx, outbuf + TRANSOP_CC20_PREAMBLE_SIZE + evp_len, &evp_len)) { + evp_ciphertext_len += evp_len; + + if(evp_ciphertext_len != len) + traceEvent(TRACE_ERROR, "encode_cc20 openssl encryption: encrypted %u bytes where %u were expected.\n", + evp_ciphertext_len, len); + } else + traceEvent(TRACE_ERROR, "encode_cc20 openssl final encryption: %s\n", openssl_err_as_string()); + } else + traceEvent(TRACE_ERROR, "encode_cc20 openssl encrpytion: %s\n", openssl_err_as_string()); + } else + traceEvent(TRACE_ERROR, "encode_cc20 openssl padding setup: %s\n", openssl_err_as_string()); + } else + traceEvent(TRACE_ERROR, "encode_cc20 openssl init: %s\n", openssl_err_as_string()); + + EVP_CIPHER_CTX_reset(ctx); + + len += TRANSOP_CC20_PREAMBLE_SIZE; /* size of data carried in UDP. */ + } else + traceEvent(TRACE_ERROR, "encode_cc20 outbuf too small."); + } else + traceEvent(TRACE_ERROR, "encode_cc20 inbuf too big to encrypt."); + + return len; +} + +/* ****************************************************** */ + +/* See transop_encode_cc20 for packet format */ +static int transop_decode_cc20(n2n_trans_op_t * arg, + uint8_t * outbuf, + size_t out_len, + const uint8_t * inbuf, + size_t in_len, + const uint8_t * peer_mac) { + int len=0; + transop_cc20_t * priv = (transop_cc20_t *)arg->priv; + uint8_t assembly[N2N_PKT_BUF_SIZE]; + + if(((in_len - TRANSOP_CC20_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE) /* Cipher text fits in assembly */ + && (in_len >= TRANSOP_CC20_PREAMBLE_SIZE) /* Has at least version, iv */ + ) + { + size_t rem=in_len; + size_t idx=0; + uint8_t cc20_enc_ver=0; + n2n_cc20_ivec_t dec_ivec = {0}; + + /* Get the encoding version to make sure it is supported */ + decode_uint8(&cc20_enc_ver, inbuf, &rem, &idx ); + + if(N2N_CC20_TRANSFORM_VERSION == cc20_enc_ver) { + /* Get the IV */ + decode_buf((uint8_t *)&dec_ivec, N2N_CC20_IVEC_SIZE, inbuf, &rem, &idx); + + traceEvent(TRACE_DEBUG, "decode_cc20 %lu", in_len); + len = (in_len - TRANSOP_CC20_PREAMBLE_SIZE); + + EVP_CIPHER_CTX *ctx = priv->dec_ctx; + int evp_len; + int evp_plaintext_len; + + if(1 == EVP_DecryptInit_ex(ctx, priv->cipher, NULL, priv->key, dec_ivec)) { + if(1 == EVP_CIPHER_CTX_set_padding(ctx, 0)) { + if(1 == EVP_DecryptUpdate(ctx, assembly, &evp_len, inbuf + TRANSOP_CC20_PREAMBLE_SIZE, len)) { + evp_plaintext_len = evp_len; + if(1 == EVP_DecryptFinal_ex(ctx, assembly + evp_len, &evp_len)) { + evp_plaintext_len += evp_len; + + if(evp_plaintext_len != len) + traceEvent(TRACE_ERROR, "decode_cc20 openssl decryption: decrypted %u bytes where %u were expected.\n", + evp_plaintext_len, len); + } else + traceEvent(TRACE_ERROR, "decode_cc20 openssl final decryption: %s\n", openssl_err_as_string()); + } else + traceEvent(TRACE_ERROR, "decode_cc20 openssl decrpytion: %s\n", openssl_err_as_string()); + } else + traceEvent(TRACE_ERROR, "decode_cc20 openssl padding setup: %s\n", openssl_err_as_string()); + } else + traceEvent(TRACE_ERROR, "decode_cc20 openssl init: %s\n", openssl_err_as_string()); + + EVP_CIPHER_CTX_reset(ctx); + + memcpy(outbuf, assembly, len); + } else + traceEvent(TRACE_ERROR, "decode_cc20 unsupported ChaCha20 version %u.", cc20_enc_ver); + } else + traceEvent(TRACE_ERROR, "decode_cc20 inbuf wrong size (%ul) to decrypt.", in_len); + + return len; +} + +/* ****************************************************** */ + +static int setup_cc20_key(transop_cc20_t *priv, const uint8_t *key, ssize_t key_size) { + uint8_t key_mat_buf[SHA256_DIGEST_LENGTH]; + + priv->cipher = EVP_chacha20(); + + /* Clear out any old possibly longer key matter. */ + memset(&(priv->key), 0, sizeof(priv->key) ); + /* The input key always gets hashed to make a more unpredictable and more complete use of the key space */ + SHA256(key, key_size, key_mat_buf); + memcpy (priv->key, key_mat_buf, SHA256_DIGEST_LENGTH); + + traceEvent(TRACE_DEBUG, "ChaCha20 key setup completed\n"); + + return(0); +} + +/* ****************************************************** */ + +static void transop_tick_cc20(n2n_trans_op_t * arg, time_t now) { ; } + +/* ****************************************************** */ + +/* ChaCha20 initialization function */ +int n2n_transop_cc20_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { + transop_cc20_t *priv; + const u_char *encrypt_key = (const u_char *)conf->encrypt_key; + size_t encrypt_key_len = strlen(conf->encrypt_key); + + memset(ttt, 0, sizeof(*ttt)); + ttt->transform_id = N2N_TRANSFORM_ID_CHACHA20; + + ttt->tick = transop_tick_cc20; + ttt->deinit = transop_deinit_cc20; + ttt->fwd = transop_encode_cc20; + ttt->rev = transop_decode_cc20; + + priv = (transop_cc20_t*) calloc(1, sizeof(transop_cc20_t)); + if(!priv) { + traceEvent(TRACE_ERROR, "cannot allocate transop_cc20_t memory"); + return(-1); + } + ttt->priv = priv; + + /* Setup openssl's reusable evp_* contexts for encryption and decryption*/ + if(!(priv->enc_ctx = EVP_CIPHER_CTX_new())) { + traceEvent(TRACE_ERROR, "openssl's evp_* encryption context creation: %s\n", openssl_err_as_string()); + return(-1); + } + + if(!(priv->dec_ctx = EVP_CIPHER_CTX_new())) { + traceEvent(TRACE_ERROR, "openssl's evp_* decryption context creation: %s\n", openssl_err_as_string()); + return(-1); + } + + /* Setup the cipher and key */ + return(setup_cc20_key(priv, encrypt_key, encrypt_key_len)); +} + +#endif /* HAVE_OPENSSL_1_1 */ From c741a3a6cbea5c1c3b73e49cc5d6ce4565204316 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Sun, 26 Apr 2020 20:20:59 +0200 Subject: [PATCH 02/15] added full iv output to debug trace --- transform_cc20.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/transform_cc20.c b/transform_cc20.c index d6e2ee1..f9b2ab2 100644 --- a/transform_cc20.c +++ b/transform_cc20.c @@ -112,7 +112,7 @@ static int transop_encode_cc20(n2n_trans_op_t * arg, size_t idx=0; n2n_cc20_ivec_t enc_ivec = {0}; - traceEvent(TRACE_DEBUG, "encode_cc20 %lu", in_len); + traceEvent(TRACE_DEBUG, "encode_cc20 %lu bytes", in_len); /* Encode the ChaCha20 format version. */ encode_uint8(outbuf, &idx, N2N_CC20_TRANSFORM_VERSION); @@ -120,6 +120,9 @@ static int transop_encode_cc20(n2n_trans_op_t * arg, /* Generate and encode the IV. */ set_cc20_iv(priv, enc_ivec); encode_buf(outbuf, &idx, &enc_ivec, N2N_CC20_IVEC_SIZE); + traceEvent(TRACE_DEBUG, "encode_cc20 iv=%016llx:%016llx", + htobe64(*(uint64_t*)&enc_ivec[0]), + htobe64(*(uint64_t*)&enc_ivec[8]) ); /* Encrypt the assembly contents and write the ciphertext after the iv. */ /* len is set to the length of the cipher plain text to be encrpyted @@ -190,11 +193,14 @@ static int transop_decode_cc20(n2n_trans_op_t * arg, decode_uint8(&cc20_enc_ver, inbuf, &rem, &idx ); if(N2N_CC20_TRANSFORM_VERSION == cc20_enc_ver) { + traceEvent(TRACE_DEBUG, "decode_cc20 %lu bytes", in_len); + len = (in_len - TRANSOP_CC20_PREAMBLE_SIZE); + /* Get the IV */ decode_buf((uint8_t *)&dec_ivec, N2N_CC20_IVEC_SIZE, inbuf, &rem, &idx); - - traceEvent(TRACE_DEBUG, "decode_cc20 %lu", in_len); - len = (in_len - TRANSOP_CC20_PREAMBLE_SIZE); + traceEvent(TRACE_DEBUG, "decode_cc20 iv=%016llx:%016llx", + htobe64(*(uint64_t*)&dec_ivec[0]), + htobe64(*(uint64_t*)&dec_ivec[8]) ); EVP_CIPHER_CTX *ctx = priv->dec_ctx; int evp_len; From 3ecdff429713b8af13da3242ecffc6eed8a233a7 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Sun, 26 Apr 2020 20:35:01 +0200 Subject: [PATCH 03/15] made openssl_err_as_string static to avoid compile error (also defined in transform_aes.c) --- transform_cc20.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transform_cc20.c b/transform_cc20.c index f9b2ab2..389cfe5 100644 --- a/transform_cc20.c +++ b/transform_cc20.c @@ -61,7 +61,7 @@ static int transop_deinit_cc20(n2n_trans_op_t *arg) { /* get any erorr message out of openssl taken from https://en.wikibooks.org/wiki/OpenSSL/Error_handling */ -char *openssl_err_as_string (void) { +static char *openssl_err_as_string (void) { BIO *bio = BIO_new (BIO_s_mem ()); ERR_print_errors (bio); char *buf = NULL; From 7c2648c1e2f9cd9cba5c72afc88a826703c5dee6 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Tue, 12 May 2020 16:49:07 +0545 Subject: [PATCH 04/15] added cli option for ChaCha20 (-A4) --- edge.c | 63 +++++++++++++++++++++++++++++++++++++++++++--------- edge_utils.c | 2 +- n2n.h | 1 + 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/edge.c b/edge.c index 5b470c4..16f2174 100644 --- a/edge.c +++ b/edge.c @@ -143,7 +143,7 @@ static void help() { #ifndef __APPLE__ "[-D] " #endif - "[-r] [-E] [-v] [-i ] [-L ] [-t ] [-A] [-h]\n\n"); + "[-r] [-E] [-v] [-i ] [-L ] [-t ] [-A[]] [-h]\n\n"); #if defined(N2N_CAN_NAME_IFACE) printf("-d | tun device name\n"); @@ -172,8 +172,13 @@ static void help() { " | causes connections stall when not properly supported.\n"); #endif printf("-r | Enable packet forwarding through n2n community.\n"); + printf("-A1 | Disable payload encryption. Do not use with -k.\n"); + printf("-A2 | Use Twofish for payload encryption (default). Requires a key.\n"); #ifdef N2N_HAVE_AES - printf("-A | Use AES CBC for encryption (default=use twofish).\n"); + printf("-A3 or -A (deprecated) | Use AES-CBC for payload encryption. Requires a key.\n"); +#endif +#ifdef HAVE_OPENSSL_1_1 + printf("-A4 | Use ChaCha20 for payload encryption. Requires a key.\n"); #endif printf("-E | Accept multicast MAC addresses (default=drop).\n"); printf("-S | Do not connect P2P. Always use the supernode.\n"); @@ -271,7 +276,6 @@ static int setOption(int optkey, char *optargument, n2n_priv_config_t *ec, n2n_e if(conf->encrypt_key) free(conf->encrypt_key); if(conf->transop_id == N2N_TRANSFORM_ID_NULL) conf->transop_id = N2N_TRANSFORM_ID_TWOFISH; - conf->encrypt_key = strdup(optargument); traceEvent(TRACE_DEBUG, "encrypt_key = '%s'\n", conf->encrypt_key); break; @@ -283,13 +287,52 @@ static int setOption(int optkey, char *optargument, n2n_priv_config_t *ec, n2n_e break; } -#ifdef N2N_HAVE_AES case 'A': { - conf->transop_id = N2N_TRANSFORM_ID_AESCBC; + int cipher = N2N_TRANSFORM_ID_AESCBC; // default, if '-A' only + if (optargument) { + cipher = atoi(optargument); + } else { + traceEvent(TRACE_NORMAL, "the use of the solitary -A switch is deprecated and might not be supported in future versions. " + "please use -A3 instead to choose a the AES-CBC cipher for payload encryption."); + } + /* even though 'cipher' and 'conf->transop_id' share the same encoding scheme, + * a switch-statement under conditional compilation is used to sort out the + * unsupported ciphers */ + switch (cipher) { + case 1: + { + conf->transop_id = N2N_TRANSFORM_ID_NULL; + break; + } + case 2: + { + conf->transop_id = N2N_TRANSFORM_ID_TWOFISH; + break; + } +#ifdef N2N_HAVE_AES + case 3: + { + conf->transop_id = N2N_TRANSFORM_ID_AESCBC; + break; + } +#endif +#ifdef HAVE_OPENSSL_1_1 + case 4: + { + conf->transop_id = N2N_TRANSFORM_ID_CHACHA20; + break; + } +#endif + default: + { + conf->transop_id = N2N_TRANSFORM_ID_INVAL; + traceEvent(TRACE_NORMAL, "the %s cipher given by -A_ option is not supported in this version.", transop_str(cipher)); + exit(1); + } + } break; } -#endif case 'l': /* supernode-list */ if(optargument) { @@ -398,10 +441,7 @@ static int loadFromCLI(int argc, char *argv[], n2n_edge_conf_t *conf, n2n_priv_c u_char c; while((c = getopt_long(argc, argv, - "k:a:bc:Eu:g:m:M:s:d:l:p:fvhrt:i:SDL:" -#ifdef N2N_HAVE_AES - "A" -#endif + "k:a:bc:Eu:g:m:M:s:d:l:p:fvhrt:i:SDL:A::" #ifdef __linux__ "T:" #endif @@ -682,7 +722,8 @@ int main(int argc, char* argv[]) { #if defined(HAVE_OPENSSL_1_1) traceEvent(TRACE_NORMAL, "Using %s", OpenSSL_version(0)); #endif - + traceEvent(TRACE_NORMAL, "Using %s cipher.", transop_str(conf.transop_id)); + /* Random seed */ srand(time(NULL)); diff --git a/edge_utils.c b/edge_utils.c index 9376503..454c30e 100644 --- a/edge_utils.c +++ b/edge_utils.c @@ -133,7 +133,7 @@ struct n2n_edge { /* ************************************** */ -static const char* transop_str(enum n2n_transform tr) { +const char* transop_str(enum n2n_transform tr) { switch(tr) { case N2N_TRANSFORM_ID_NULL: return("null"); case N2N_TRANSFORM_ID_TWOFISH: return("twofish"); diff --git a/n2n.h b/n2n.h index 5c23480..c41098b 100644 --- a/n2n.h +++ b/n2n.h @@ -354,5 +354,6 @@ int quick_edge_init(char *device_name, char *community_name, int sn_init(n2n_sn_t *sss); void sn_term(n2n_sn_t *sss); int run_sn_loop(n2n_sn_t *sss, int *keep_running); +const char* transop_str(enum n2n_transform tr); #endif /* _N2N_H_ */ From 05e96bb8feed0094d16d778ac86629b5f3d093f7 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Tue, 12 May 2020 17:19:40 +0545 Subject: [PATCH 05/15] tried to resolve conflict --- edge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/edge.c b/edge.c index 16f2174..9a3c56d 100644 --- a/edge.c +++ b/edge.c @@ -441,7 +441,7 @@ static int loadFromCLI(int argc, char *argv[], n2n_edge_conf_t *conf, n2n_priv_c u_char c; while((c = getopt_long(argc, argv, - "k:a:bc:Eu:g:m:M:s:d:l:p:fvhrt:i:SDL:A::" + "k:a:bc:Eu:g:m:M:s:d:l:p:fvhrt:i:SDL:zA::" #ifdef __linux__ "T:" #endif From 12aea29abfd665cc1742a9232238dca97e06aaf9 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Tue, 12 May 2020 17:24:37 +0545 Subject: [PATCH 06/15] tried to resolve conflict - part II --- edge.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/edge.c b/edge.c index 9a3c56d..9e100f7 100644 --- a/edge.c +++ b/edge.c @@ -441,7 +441,8 @@ static int loadFromCLI(int argc, char *argv[], n2n_edge_conf_t *conf, n2n_priv_c u_char c; while((c = getopt_long(argc, argv, - "k:a:bc:Eu:g:m:M:s:d:l:p:fvhrt:i:SDL:zA::" + "k:a:bc:Eu:g:m:M:s:d:l:p:fvhrt:i:SDL:z" + "A::" #ifdef __linux__ "T:" #endif From 928fc9f22e95a04797f73d95665ce51c1f665a4f Mon Sep 17 00:00:00 2001 From: emanuele-f Date: Sat, 23 May 2020 14:33:10 +0200 Subject: [PATCH 07/15] Add ability to insert linux routes in n2n The new -n option can now be used to setup routes directly from the edge command line. It supports both network routes and default gateway routes. Here is an example: - "-n 192.168.100.0/24:192.168.99.1" routes the 192.168.100.0/24 network traffic via 192.168.99.1 - "-n 0.0.0.0/0:192.168.99.1" routes all the host traffic via 192.168.99.1 --- edge.c | 42 +++++- edge_utils.c | 357 ++++++++++++++++++++++++++++++++++++++++++++++++- n2n.h | 12 +- tuntap_linux.c | 5 + 4 files changed, 407 insertions(+), 9 deletions(-) diff --git a/edge.c b/edge.c index f00aa05..c303240 100644 --- a/edge.c +++ b/edge.c @@ -135,6 +135,7 @@ static void help() { #endif /* #ifndef WIN32 */ #ifdef __linux__ "[-T ]" + "[-n cidr:gateway] " #endif "[-m ] " "-l \n" @@ -181,6 +182,7 @@ static void help() { printf("-S | Do not connect P2P. Always use the supernode.\n"); #ifdef __linux__ printf("-T | TOS for packets (e.g. 0x48 for SSH like priority)\n"); + printf("-n | Route an IPv4 network via the gw. Use 0.0.0.0/0 for the default gw. Can be set multiple times.\n"); #endif printf("-v | Make more verbose. Repeat as required.\n"); printf("-t | Management UDP Port (for multiple edges on a machine).\n"); @@ -347,6 +349,43 @@ static int setOption(int optkey, char *optargument, n2n_priv_config_t *ec, n2n_e break; } + + case 'n': + { + char cidr_net[64], gateway[64]; + n2n_route_t route; + + if(sscanf(optargument, "%63[^/]/%d:%63s", cidr_net, &route.net_bitlen, gateway) != 3) { + traceEvent(TRACE_WARNING, "Bad cidr/gateway format '%d'. See -h.", optargument); + break; + } + + route.net_addr = inet_addr(cidr_net); + route.gateway = inet_addr(gateway); + + if((route.net_bitlen < 0) || (route.net_bitlen > 32)) { + traceEvent(TRACE_WARNING, "Bad prefix '%d' in '%s'", route.net_bitlen, optargument); + break; + } + + if(route.net_addr == INADDR_NONE) { + traceEvent(TRACE_WARNING, "Bad network '%s' in '%s'", cidr_net, optargument); + break; + } + + if(route.net_addr == INADDR_NONE) { + traceEvent(TRACE_WARNING, "Bad gateway '%s' in '%s'", gateway, optargument); + break; + } + + traceEvent(TRACE_DEBUG, "Adding %s/%d via %s", cidr_net, route.net_bitlen, gateway); + + conf->routes = realloc(conf->routes, sizeof(struct n2n_route) * (conf->num_routes + 1)); + conf->routes[conf->num_routes] = route; + conf->num_routes++; + + break; + } #endif case 's': /* Subnet Mask */ @@ -411,7 +450,7 @@ static int loadFromCLI(int argc, char *argv[], n2n_edge_conf_t *conf, n2n_priv_c "A" #endif #ifdef __linux__ - "T:" + "T:n:" #endif , long_options, NULL)) != '?') { @@ -766,6 +805,7 @@ int main(int argc, char* argv[]) { /* Cleanup */ edge_term(eee); + edge_term_conf(&conf); tuntap_close(&tuntap); if(conf.encrypt_key) free(conf.encrypt_key); diff --git a/edge_utils.c b/edge_utils.c index 38910ed..6f2faf6 100644 --- a/edge_utils.c +++ b/edge_utils.c @@ -41,6 +41,11 @@ #define ARP_PERIOD_INTERVAL (10) /* sec */ #endif +#ifdef __linux__ +#include +#include +#endif + #define ETH_FRAMESIZE 14 #define IP4_SRCOFFSET 12 #define IP4_DSTOFFSET 16 @@ -60,7 +65,9 @@ static void check_peer_registration_needed(n2n_edge_t * eee, const n2n_mac_t mac, const n2n_sock_t * peer); static int edge_init_sockets(n2n_edge_t *eee, int udp_local_port, int mgmt_port, uint8_t tos); -static void supernode2addr(n2n_sock_t * sn, const n2n_sn_name_t addrIn); +static int edge_init_routes(n2n_edge_t *eee, n2n_route_t *routes, uint16_t num_routes); +static void edge_cleanup_routes(n2n_edge_t *eee); +static int supernode2addr(n2n_sock_t * sn, const n2n_sn_name_t addrIn); static void check_known_peer_sock_change(n2n_edge_t * eee, uint8_t from_supernode, const n2n_mac_t mac, @@ -109,6 +116,7 @@ struct n2n_edge { tuntap_dev device; /**< All about the TUNTAP device */ n2n_trans_op_t transop; /**< The transop to use when encoding */ n2n_cookie_t last_cookie; /**< Cookie sent in last REGISTER_SUPER. */ + n2n_route_t *sn_route_to_clean; /**< Supernode route to clean */ /* Sockets */ n2n_sock_t supernode; @@ -256,7 +264,12 @@ n2n_edge_t* edge_init(const tuntap_dev *dev, const n2n_edge_conf_t *conf, int *r traceEvent(TRACE_WARNING, "Encryption is disabled in edge"); if(edge_init_sockets(eee, conf->local_port, conf->mgmt_port, conf->tos) < 0) { - traceEvent(TRACE_ERROR, "Error: socket setup failed"); + traceEvent(TRACE_ERROR, "socket setup failed"); + goto edge_init_error; + } + + if(edge_init_routes(eee, conf->routes, conf->num_routes) < 0) { + traceEvent(TRACE_ERROR, "routes setup failed"); goto edge_init_error; } @@ -309,16 +322,16 @@ static int is_valid_peer_sock(const n2n_sock_t *sock) { * REVISIT: This is a really bad idea. The edge will block completely while the * hostname resolution is performed. This could take 15 seconds. */ -static void supernode2addr(n2n_sock_t * sn, const n2n_sn_name_t addrIn) { +static int supernode2addr(n2n_sock_t * sn, const n2n_sn_name_t addrIn) { n2n_sn_name_t addr; const char *supernode_host; + int rv = 0; memcpy(addr, addrIn, N2N_EDGE_SN_HOST_SIZE); supernode_host = strtok(addr, ":"); - if(supernode_host) - { + if(supernode_host) { in_addr_t sn_addr; char *supernode_port = strtok(NULL, ":"); const struct addrinfo aihints = {0, PF_INET, 0, 0, 0, NULL, NULL, NULL}; @@ -350,6 +363,7 @@ static void supernode2addr(n2n_sock_t * sn, const n2n_sn_name_t addrIn) { { /* Should only return IPv4 addresses due to aihints. */ traceEvent(TRACE_WARNING, "Failed to resolve supernode IPv4 address for %s", supernode_host); + rv = -1; } freeaddrinfo(ainfo); /* free everything allocated by getaddrinfo(). */ @@ -359,10 +373,15 @@ static void supernode2addr(n2n_sock_t * sn, const n2n_sn_name_t addrIn) { sn_addr = inet_addr(supernode_host); /* uint32_t */ memcpy(sn->addr.v4, &(sn_addr), IPV4_SIZE); sn->family=AF_INET; + rv = -2; } - } else + } else { traceEvent(TRACE_WARNING, "Wrong supernode parameter (-l )"); + rv = -3; + } + + return(rv); } /* ************************************** */ @@ -1907,6 +1926,9 @@ void edge_term(n2n_edge_t * eee) { clear_peer_list(&eee->known_peers); eee->transop.deinit(&eee->transop); + + edge_cleanup_routes(eee); + free(eee); } @@ -1978,6 +2000,322 @@ static int edge_init_sockets(n2n_edge_t *eee, int udp_local_port, int mgmt_port, /* ************************************** */ +#ifdef __linux__ + +static uint32_t get_gateway_ip() { + FILE *fd; + char *token = NULL; + char *gateway_ip_str = NULL; + char buf[256]; + uint32_t gateway = 0; + + if(!(fd = fopen("/proc/net/route", "r"))) + return(0); + + while(fgets(buf, sizeof(buf), fd)) { + if(strtok(buf, "\t") && (token = strtok(NULL, "\t")) && (!strcmp(token, "00000000"))) { + token = strtok(NULL, "\t"); + + if(token) { + struct in_addr addr; + + addr.s_addr = strtoul(token, NULL, 16); + gateway_ip_str = inet_ntoa(addr); + + if(gateway_ip_str) { + gateway = addr.s_addr; + break; + } + } + } + } + + fclose(fd); + + return(gateway); +} + +static char* route_cmd_to_str(int cmd, const n2n_route_t *route, char *buf, size_t bufsize) { + const char *cmd_str; + struct in_addr addr; + char netbuf[64], gwbuf[64]; + + switch(cmd) { + case RTM_NEWROUTE: + cmd_str = "ADD"; + break; + case RTM_DELROUTE: + cmd_str = "DELETE"; + break; + default: + cmd_str = "?"; + } + + addr.s_addr = route->net_addr; + inet_ntop(AF_INET, &addr, netbuf, sizeof(netbuf)); + addr.s_addr = route->gateway; + inet_ntop(AF_INET, &addr, gwbuf, sizeof(gwbuf)); + + snprintf(buf, bufsize, "[%s] %s/%d via %s", cmd_str, netbuf, route->net_bitlen, gwbuf); + + return(buf); +} + +/* Adapted from https://olegkutkov.me/2019/08/29/modifying-linux-network-routes-using-netlink/ */ +#define NLMSG_TAIL(nmsg) \ + ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) + +/* Add new data to rtattr */ +static int rtattr_add(struct nlmsghdr *n, int maxlen, int type, const void *data, int alen) +{ + int len = RTA_LENGTH(alen); + struct rtattr *rta; + + if(NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { + traceEvent(TRACE_ERROR, "rtattr_add error: message exceeded bound of %d\n", maxlen); + return -1; + } + + rta = NLMSG_TAIL(n); + rta->rta_type = type; + rta->rta_len = len; + + if(alen) + memcpy(RTA_DATA(rta), data, alen); + + n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); + + return 0; +} + +static int routectl(int cmd, int flags, n2n_route_t *route, int if_idx, uint8_t ignore_failure) { + int rv = -1; + int rv2; + char nl_buf[8192]; /* >= 8192 to avoid truncation, see "man 7 netlink" */ + struct iovec iov; + struct msghdr msg; + struct sockaddr_nl sa; + uint8_t read_reply = 1; + int nl_sock; + + struct { + struct nlmsghdr n; + struct rtmsg r; + char buf[4096]; + } nl_request; + + if((nl_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) { + traceEvent(TRACE_ERROR, "netlink socket creation failed [%d]: %s", errno, strerror(errno)); + return(-1); + } + + /* Subscribe to route change events */ + iov.iov_base = nl_buf; + iov.iov_len = sizeof(nl_buf); + + memset(&sa, 0, sizeof(sa)); + sa.nl_family = PF_NETLINK; + sa.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_NOTIFY; + sa.nl_pid = getpid(); + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = &sa; + msg.msg_namelen = sizeof(sa); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + /* Subscribe to route events */ + if(bind(nl_sock, (struct sockaddr*)&sa, sizeof(sa)) == -1) { + traceEvent(TRACE_ERROR, "netlink socket bind failed [%d]: %s", errno, strerror(errno)); + goto out; + } + + /* Initialize request structure */ + memset(&nl_request, 0, sizeof(nl_request)); + nl_request.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + nl_request.n.nlmsg_flags = NLM_F_REQUEST | flags; + nl_request.n.nlmsg_type = cmd; + nl_request.r.rtm_family = AF_INET; + nl_request.r.rtm_table = RT_TABLE_MAIN; + nl_request.r.rtm_scope = RT_SCOPE_NOWHERE; + + /* Set additional flags if NOT deleting route */ + if(cmd != RTM_DELROUTE) { + nl_request.r.rtm_protocol = RTPROT_BOOT; + nl_request.r.rtm_type = RTN_UNICAST; + } + + nl_request.r.rtm_family = AF_INET; + nl_request.r.rtm_dst_len = route->net_bitlen; + + /* Select scope, for simplicity we supports here only IPv6 and IPv4 */ + if(nl_request.r.rtm_family == AF_INET6) + nl_request.r.rtm_scope = RT_SCOPE_UNIVERSE; + else + nl_request.r.rtm_scope = RT_SCOPE_LINK; + + /* Set gateway */ + if(route->net_bitlen) { + if(rtattr_add(&nl_request.n, sizeof(nl_request), RTA_GATEWAY, &route->gateway, 4) < 0) + goto out; + + nl_request.r.rtm_scope = 0; + nl_request.r.rtm_family = AF_INET; + } + + /* Don't set destination and interface in case of default gateways */ + if(route->net_bitlen) { + /* Set destination network */ + if(rtattr_add(&nl_request.n, sizeof(nl_request), /*RTA_NEWDST*/ RTA_DST, &route->net_addr, 4) < 0) + goto out; + + /* Set interface */ + if(if_idx > 0) { + if(rtattr_add(&nl_request.n, sizeof(nl_request), RTA_OIF, &if_idx, sizeof(int)) < 0) + goto out; + } + } + + /* Send message to the netlink */ + if((rv2 = send(nl_sock, &nl_request, sizeof(nl_request), 0)) != sizeof(nl_request)) { + traceEvent(TRACE_ERROR, "netlink send failed [%d]: %s", errno, strerror(errno)); + goto out; + } + + /* Wait for the route notification. Assume that the first reply we get is the correct one. */ + while(read_reply) { + ssize_t len = recvmsg(nl_sock, &msg, 0); + struct nlmsghdr *nh; + + for(nh = (struct nlmsghdr *)nl_buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) { + /* Stop after the first reply */ + read_reply = 0; + + if(nh->nlmsg_type == NLMSG_ERROR) { + char buf[256]; + struct nlmsgerr *err = NLMSG_DATA(nh); + int errcode = err->error; + + if(errcode < 0) + errcode = -errcode; + + /* Ignore EEXIST as existing rules are ok */ + if(!ignore_failure && (errcode != EEXIST)) { + traceEvent(TRACE_ERROR, "[err=%d] route: %s", errcode, route_cmd_to_str(cmd, route, buf, sizeof(buf))); + goto out; + } + } + + if(nh->nlmsg_type == NLMSG_DONE) + break; + + if(nh->nlmsg_type == cmd) + break; + } + } + + rv = 0; + +out: + close(nl_sock); + + return(rv); +} +#endif + +/* Add the user-provided routes to the linux routing table. Network routes + * are bound to the n2n TAP device, so they are automatically removed when + * the TAP device is destroyed. */ +static int edge_init_routes(n2n_edge_t *eee, n2n_route_t *routes, uint16_t num_routes) { +#ifdef __linux__ + int i; + + for(i=0; inet_addr == 0) && (route->net_bitlen == 0)) { + /* This is a default gateway rule. We need to: + * + * 1. Add a route to the supernode via the host internet gateway + * 2. Add the new default gateway route + * + * Instead of modifying the system default gateway, we use the trick + * of adding a route to the 0.0.0.0/1 network, which takes precedence + * over the default gateway (0.0.0.0/0). This leaves the default + * gateway unchanged so that after n2n is stopped the cleanup is + * easier. + */ + n2n_sock_t sn; + n2n_route_t custom_route; + + if(eee->sn_route_to_clean) { + traceEvent(TRACE_ERROR, "Only one default gateway route allowed"); + return(-1); + } + + if(eee->conf.sn_num != 1) { + traceEvent(TRACE_ERROR, "Only one supernode supported with routes"); + return(-1); + } + + if(supernode2addr(&sn, eee->conf.sn_ip_array[0]) < 0) + return(-1); + + if(sn.family != AF_INET) { + traceEvent(TRACE_ERROR, "Only IPv4 routes supported"); + return(-1); + } + + custom_route.net_addr = *((u_int32_t*)sn.addr.v4); + custom_route.net_bitlen = 32; + custom_route.gateway = get_gateway_ip(); + + if(!custom_route.gateway) { + traceEvent(TRACE_ERROR, "could not determine the gateway IP address"); + return(-1); + } + + /* ip route add supernode via internet_gateway */ + if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, &custom_route, -1, 0) < 0) + return(-1); + + /* Save the route to delete it when n2n is stopped */ + eee->sn_route_to_clean = calloc(1, sizeof(n2n_route_t)); + + /* Store a copy of the rules into the runtime to delete it during shutdown */ + if(eee->sn_route_to_clean) + *eee->sn_route_to_clean = custom_route; + + /* ip route add 0.0.0.0/1 via n2n_gateway */ + custom_route.net_addr = 0; + custom_route.net_bitlen = 1; + custom_route.gateway = route->gateway; + + if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, &custom_route, eee->device.if_idx, 0) < 0) + return(-1); + } else { + /* ip route add net via n2n_gateway */ + if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, route, eee->device.if_idx, 0) < 0) + return(-1); + } + } +#endif + + return(0); +} + +/* ************************************** */ + +static void edge_cleanup_routes(n2n_edge_t *eee) { + if(eee->sn_route_to_clean) { + /* ip route del supernode via internet_gateway */ + routectl(RTM_DELROUTE, 0, eee->sn_route_to_clean, -1, 1 /* can fail as we have dropped capabilities */); + free(eee->sn_route_to_clean); + } +} + +/* ************************************** */ + void edge_init_conf_defaults(n2n_edge_conf_t *conf) { memset(conf, 0, sizeof(*conf)); @@ -1998,6 +2336,12 @@ void edge_init_conf_defaults(n2n_edge_conf_t *conf) { /* ************************************** */ +void edge_term_conf(n2n_edge_conf_t *conf) { + if(conf->routes) free(conf->routes); +} + +/* ************************************** */ + const n2n_edge_conf_t* edge_get_conf(const n2n_edge_t *eee) { return(&eee->conf); } @@ -2050,6 +2394,7 @@ int quick_edge_init(char *device_name, char *community_name, rv = run_edge_loop(eee, keep_on_running); edge_term(eee); + edge_term_conf(&conf); quick_edge_init_end: tuntap_close(&tuntap); diff --git a/n2n.h b/n2n.h index ada157f..017e80c 100644 --- a/n2n.h +++ b/n2n.h @@ -73,8 +73,6 @@ #include #ifdef __linux__ -#include -#include #define N2N_CAN_NAME_IFACE 1 #endif /* #ifdef __linux__ */ @@ -139,6 +137,7 @@ typedef struct ether_hdr ether_hdr_t; #ifndef WIN32 typedef struct tuntap_dev { int fd; + int if_idx; uint8_t mac_addr[6]; uint32_t ip_addr, device_mask; uint16_t mtu; @@ -211,11 +210,19 @@ struct peer_info { typedef char n2n_sn_name_t[N2N_EDGE_SN_HOST_SIZE]; +typedef struct n2n_route { + in_addr_t net_addr; + int net_bitlen; + in_addr_t gateway; +} n2n_route_t; + typedef struct n2n_edge_conf { n2n_sn_name_t sn_ip_array[N2N_EDGE_NUM_SUPERNODES]; + n2n_route_t *routes; /**< Networks to route through n2n */ n2n_community_t community_name; /**< The community. 16 full octets. */ n2n_transform_t transop_id; /**< The transop to use. */ uint16_t compression; /**< Compress outgoing data packets before encryption */ + uint16_t num_routes; /**< Number of routes in routes */ uint8_t dyn_ip_mode; /**< Interface IP address is dynamically allocated, eg. DHCP. */ uint8_t allow_routing; /**< Accept packet no to interface address. */ uint8_t drop_multicast; /**< Multicast ethernet addresses. */ @@ -344,6 +351,7 @@ void edge_init_conf_defaults(n2n_edge_conf_t *conf); int edge_verify_conf(const n2n_edge_conf_t *conf); int edge_conf_add_supernode(n2n_edge_conf_t *conf, const char *ip_and_port); const n2n_edge_conf_t* edge_get_conf(const n2n_edge_t *eee); +void edge_term_conf(n2n_edge_conf_t *conf); /* Public functions */ n2n_edge_t* edge_init(const tuntap_dev *dev, const n2n_edge_conf_t *conf, int *rv); diff --git a/tuntap_linux.c b/tuntap_linux.c index ae10445..b3f6fe5 100644 --- a/tuntap_linux.c +++ b/tuntap_linux.c @@ -21,6 +21,8 @@ #ifdef __linux__ #include +#include +#include #include #include @@ -170,6 +172,7 @@ int tuntap_open(tuntap_dev *device, sa.nl_groups = RTMGRP_LINK; sa.nl_pid = getpid(); + memset(&msg, 0, sizeof(msg)); msg.msg_name = &sa; msg.msg_namelen = sizeof(sa); msg.msg_iov = &iov; @@ -229,6 +232,8 @@ int tuntap_open(tuntap_dev *device, device->ip_addr = inet_addr(device_ip); device->device_mask = inet_addr(device_mask); + device->if_idx = if_nametoindex(dev); + return(device->fd); } From 62b953042530d5e06fb2b11019cc04b3d0ecf434 Mon Sep 17 00:00:00 2001 From: emanuele-f Date: Sat, 23 May 2020 16:44:47 +0200 Subject: [PATCH 08/15] Add missing ifdef --- edge_utils.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/edge_utils.c b/edge_utils.c index 6f2faf6..e6f0580 100644 --- a/edge_utils.c +++ b/edge_utils.c @@ -2183,6 +2183,8 @@ static int routectl(int cmd, int flags, n2n_route_t *route, int if_idx, uint8_t } /* Wait for the route notification. Assume that the first reply we get is the correct one. */ + traceEvent(TRACE_DEBUG, "waiting for netlink response..."); + while(read_reply) { ssize_t len = recvmsg(nl_sock, &msg, 0); struct nlmsghdr *nh; @@ -2307,11 +2309,13 @@ static int edge_init_routes(n2n_edge_t *eee, n2n_route_t *routes, uint16_t num_r /* ************************************** */ static void edge_cleanup_routes(n2n_edge_t *eee) { +#ifdef __linux__ if(eee->sn_route_to_clean) { /* ip route del supernode via internet_gateway */ routectl(RTM_DELROUTE, 0, eee->sn_route_to_clean, -1, 1 /* can fail as we have dropped capabilities */); free(eee->sn_route_to_clean); } +#endif } /* ************************************** */ From 0e48e2f24c33391ab9a0b73e5fba636089cabbfb Mon Sep 17 00:00:00 2001 From: emanuele-f Date: Sat, 23 May 2020 17:17:32 +0200 Subject: [PATCH 09/15] Add support for linux capabilities to proper routes cleanup --- configure.seed | 6 ++++++ edge.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ edge_utils.c | 27 +++++++++++++++------------ 3 files changed, 66 insertions(+), 12 deletions(-) diff --git a/configure.seed b/configure.seed index d1f0004..067351c 100644 --- a/configure.seed +++ b/configure.seed @@ -49,6 +49,12 @@ if test x$pcap_immediate_mode != x; then AC_DEFINE([HAVE_PCAP_IMMEDIATE_MODE], [], [Have pcap_immediate_mode]) fi +AC_CHECK_LIB([cap], [cap_get_proc], cap=true) +if test x$cap != x; then + LDFLAGS="${LDFLAGS} -lcap" + AC_DEFINE([HAVE_LIBCAP],[1],[Support for linux capabilities]) +fi + MACHINE=`uname -m` SYSTEM=`uname -s` diff --git a/edge.c b/edge.c index c303240..17b7b40 100644 --- a/edge.c +++ b/edge.c @@ -37,6 +37,21 @@ /* ***************************************************** */ +#ifdef HAVE_LIBCAP + +#include +#include + +static cap_value_t cap_values[] = { + //CAP_NET_RAW, /* Use RAW and PACKET sockets */ + CAP_NET_ADMIN /* Needed to performs routes cleanup at exit */ +}; + +int num_cap = sizeof(cap_values)/sizeof(cap_value_t); +#endif + +/* ***************************************************** */ + typedef struct n2n_priv_config { char tuntap_dev_name[N2N_IFNAMSIZ]; char ip_mode[N2N_IF_MODE_SIZE]; @@ -681,6 +696,9 @@ int main(int argc, char* argv[]) { #ifndef WIN32 struct passwd *pw = NULL; #endif +#ifdef HAVE_LIBCAP + cap_t caps; +#endif /* Defaults */ edge_init_conf_defaults(&conf); @@ -774,6 +792,22 @@ int main(int argc, char* argv[]) { #endif /* #ifndef WIN32 */ #ifndef WIN32 + +#ifdef HAVE_LIBCAP + /* Before dropping the privileges, retain capabilities to regain them in future. */ + caps = cap_get_proc(); + + cap_set_flag(caps, CAP_PERMITTED, num_cap, cap_values, CAP_SET); + cap_set_flag(caps, CAP_EFFECTIVE, num_cap, cap_values, CAP_SET); + + if((cap_set_proc(caps) != 0) || (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0)) + traceEvent(TRACE_WARNING, "Unable to retain permitted capabilities [%s]\n", strerror(errno)); +#else +#ifndef __APPLE__ + traceEvent(TRACE_WARNING, "n2n has not been compiled with libcap-dev. Some commands may fail."); +#endif +#endif /* HAVE_LIBCAP */ + if((ec.userid != 0) || (ec.groupid != 0)) { traceEvent(TRACE_NORMAL, "Dropping privileges to uid=%d, gid=%d", (signed int)ec.userid, (signed int)ec.groupid); @@ -803,6 +837,17 @@ int main(int argc, char* argv[]) { rc = run_edge_loop(eee, &keep_on_running); print_edge_stats(eee); +#ifdef HAVE_LIBCAP + /* Before completing the cleanup, regain the capabilities as some + * cleanup tasks require them (e.g. routes cleanup). */ + cap_set_flag(caps, CAP_EFFECTIVE, num_cap, cap_values, CAP_SET); + + if(cap_set_proc(caps) != 0) + traceEvent(TRACE_WARNING, "Could not regain the capabilities [%s]\n", strerror(errno)); + + cap_free(caps); +#endif + /* Cleanup */ edge_term(eee); edge_term_conf(&conf); diff --git a/edge_utils.c b/edge_utils.c index e6f0580..182eb91 100644 --- a/edge_utils.c +++ b/edge_utils.c @@ -2042,10 +2042,10 @@ static char* route_cmd_to_str(int cmd, const n2n_route_t *route, char *buf, size switch(cmd) { case RTM_NEWROUTE: - cmd_str = "ADD"; + cmd_str = "Add"; break; case RTM_DELROUTE: - cmd_str = "DELETE"; + cmd_str = "Delete"; break; default: cmd_str = "?"; @@ -2056,7 +2056,7 @@ static char* route_cmd_to_str(int cmd, const n2n_route_t *route, char *buf, size addr.s_addr = route->gateway; inet_ntop(AF_INET, &addr, gwbuf, sizeof(gwbuf)); - snprintf(buf, bufsize, "[%s] %s/%d via %s", cmd_str, netbuf, route->net_bitlen, gwbuf); + snprintf(buf, bufsize, "%s %s/%d via %s", cmd_str, netbuf, route->net_bitlen, gwbuf); return(buf); } @@ -2088,10 +2088,11 @@ static int rtattr_add(struct nlmsghdr *n, int maxlen, int type, const void *data return 0; } -static int routectl(int cmd, int flags, n2n_route_t *route, int if_idx, uint8_t ignore_failure) { +static int routectl(int cmd, int flags, n2n_route_t *route, int if_idx) { int rv = -1; int rv2; char nl_buf[8192]; /* >= 8192 to avoid truncation, see "man 7 netlink" */ + char route_buf[256]; struct iovec iov; struct msghdr msg; struct sockaddr_nl sa; @@ -2194,7 +2195,6 @@ static int routectl(int cmd, int flags, n2n_route_t *route, int if_idx, uint8_t read_reply = 0; if(nh->nlmsg_type == NLMSG_ERROR) { - char buf[256]; struct nlmsgerr *err = NLMSG_DATA(nh); int errcode = err->error; @@ -2202,8 +2202,8 @@ static int routectl(int cmd, int flags, n2n_route_t *route, int if_idx, uint8_t errcode = -errcode; /* Ignore EEXIST as existing rules are ok */ - if(!ignore_failure && (errcode != EEXIST)) { - traceEvent(TRACE_ERROR, "[err=%d] route: %s", errcode, route_cmd_to_str(cmd, route, buf, sizeof(buf))); + if(errcode != EEXIST) { + traceEvent(TRACE_ERROR, "[err=%d] route: %s", errcode, route_cmd_to_str(cmd, route, route_buf, sizeof(route_buf))); goto out; } } @@ -2211,11 +2211,14 @@ static int routectl(int cmd, int flags, n2n_route_t *route, int if_idx, uint8_t if(nh->nlmsg_type == NLMSG_DONE) break; - if(nh->nlmsg_type == cmd) + if(nh->nlmsg_type == cmd) { + traceEvent(TRACE_DEBUG, "Found netlink reply"); break; + } } } + traceEvent(TRACE_DEBUG, route_cmd_to_str(cmd, route, route_buf, sizeof(route_buf))); rv = 0; out: @@ -2278,7 +2281,7 @@ static int edge_init_routes(n2n_edge_t *eee, n2n_route_t *routes, uint16_t num_r } /* ip route add supernode via internet_gateway */ - if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, &custom_route, -1, 0) < 0) + if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, &custom_route, -1) < 0) return(-1); /* Save the route to delete it when n2n is stopped */ @@ -2293,11 +2296,11 @@ static int edge_init_routes(n2n_edge_t *eee, n2n_route_t *routes, uint16_t num_r custom_route.net_bitlen = 1; custom_route.gateway = route->gateway; - if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, &custom_route, eee->device.if_idx, 0) < 0) + if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, &custom_route, eee->device.if_idx) < 0) return(-1); } else { /* ip route add net via n2n_gateway */ - if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, route, eee->device.if_idx, 0) < 0) + if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, route, eee->device.if_idx) < 0) return(-1); } } @@ -2312,7 +2315,7 @@ static void edge_cleanup_routes(n2n_edge_t *eee) { #ifdef __linux__ if(eee->sn_route_to_clean) { /* ip route del supernode via internet_gateway */ - routectl(RTM_DELROUTE, 0, eee->sn_route_to_clean, -1, 1 /* can fail as we have dropped capabilities */); + routectl(RTM_DELROUTE, 0, eee->sn_route_to_clean, -1); free(eee->sn_route_to_clean); } #endif From 2a28bd1952c0fdded5317ef1d0ee50d8aeec8b9d Mon Sep 17 00:00:00 2001 From: Emanuele Faranda Date: Sat, 23 May 2020 15:35:51 +0000 Subject: [PATCH 10/15] New routing instructions --- README.md | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 66d910f..0ef019e 100644 --- a/README.md +++ b/README.md @@ -47,35 +47,22 @@ Now the supernode service should be up and running on port 1234. On your edge no ## Routing the traffic -On linux, n2n provides a standard TAP interface, so routing works gracefully via the standard system utilities as follows. +Reaching a remote network or tunneling all the internet traffic via n2n are two common tasks which require a proper routing setup. In this context, the `server` is the edge node which provides access to the remote network/internet, whereas the `client` is the connecting edge node. -In this example host1 is the edge router (with n2n IP 192.168.100.1), whereas host2 is the client. - -Here is how to configure host1: +In order to enable routing, the `server` must be configured as follows: 1. Add the `-r` option to the edge options to enable routing 2. Enable packet forwarding with `sudo sysctl -w net.ipv4.ip_forward=1` -3. Possibly configure iptables to `ACCEPT` the packets on the `FORWARD` chain. - -On host2, run the `edge` program as normal to join the host1 community. - -In order to forward all the internet traffic via host2: +3. Enable IP masquerading: `sudo iptables -t nat -A POSTROUTING -j MASQUERADE` -```sh -# Determine the current gateway (e.g. 192.168.1.1) -$ ip route show default - -# Add a route to reach the supernode via such gateway -$ sudo ip route add supernode.ntop.org via 192.168.1.1 +On the client side, the easiest way to configure routing is via the `-n` option. For example: -# Forward all the internet traffic via host1 -$ sudo ip route del default -$ sudo ip route add default via 192.168.100.1 -``` +- In order to connect to the remote network `192.168.100.0/24`, use `-n 192.168.100.0/24:10.0.0.1` +- In order to tunnel all the internet traffic, use `-n 0.0.0.0/0:10.0.0.1` -This process can be greatly simplified by using the [n2n_gateway.sh](doc/n2n_gateway.sh) script. +10.0.0.1 is the IP address of the gateway to use to route the specified network. It should correspond to the IP address of the `server` within n2n. Multiple `-n` options can be specified. -See [Routing.md](doc/Routing.md) for other use cases and in depth explanation. +As an alternative to the `-n` option, the `ip route` linux command can be manually used. See the [n2n_gateway.sh](doc/n2n_gateway.sh) script for an example. See also [Routing.md](doc/Routing.md) for other use cases and in depth explanation. ## Manual Compilation From a014f5a68bf7243abd2cc95388ff036b127cd0e9 Mon Sep 17 00:00:00 2001 From: emanuele-f Date: Sun, 24 May 2020 11:25:12 +0200 Subject: [PATCH 11/15] Windows compilation fix --- Makefile.in | 3 --- edge.c | 4 ++-- sn.c | 4 ++-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Makefile.in b/Makefile.in index 14f5599..fbb0c29 100644 --- a/Makefile.in +++ b/Makefile.in @@ -91,9 +91,6 @@ example_sn_embed: example_sn_embed.c $(N2N_LIB) n2n.h example_edge_embed: example_edge_embed.c $(N2N_LIB) n2n.h $(CC) $(CFLAGS) $< $(LDFLAGS) $(N2N_LIB) $(LIBS_EDGE) -o $@ -.c.o: n2n.h n2n_transforms.h n2n_wire.h twofish.h Makefile - $(CC) $(CFLAGS) -c $< -o $@ - %.gz : % gzip -c $< > $@ diff --git a/edge.c b/edge.c index 17b7b40..c45d5d4 100644 --- a/edge.c +++ b/edge.c @@ -660,7 +660,7 @@ static void daemonize() { static int keep_on_running; -#ifdef __linux__ +#if defined(__linux__) || defined(WIN32) #ifdef WIN32 BOOL WINAPI term_handler(DWORD sig) #else @@ -682,7 +682,7 @@ static void term_handler(int sig) return(TRUE); #endif } -#endif +#endif /* defined(__linux__) || defined(WIN32) */ /* *************************************************** */ diff --git a/sn.c b/sn.c index 0a86a38..9d7c26b 100644 --- a/sn.c +++ b/sn.c @@ -930,7 +930,7 @@ static void dump_registrations(int signo) { static int keep_running; -#ifdef __linux__ +#if defined(__linux__) || defined(WIN32) #ifdef WIN32 BOOL WINAPI term_handler(DWORD sig) #else @@ -952,7 +952,7 @@ static void term_handler(int sig) return(TRUE); #endif } -#endif +#endif /* defined(__linux__) || defined(WIN32) */ /* *************************************************** */ From 5044fcde2675bb73f2ae2cc1923e608f11cf1589 Mon Sep 17 00:00:00 2001 From: emanuele-f Date: Sun, 24 May 2020 11:36:56 +0200 Subject: [PATCH 12/15] Add linux capabilities dependency to cmake --- CMakeLists.txt | 8 ++++++++ edge_utils.c | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 674b05e..fe2319f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,6 +92,14 @@ target_link_libraries(example_edge_embed n2n) add_executable(example_sn_embed example_sn_embed.c) target_link_libraries(example_sn_embed n2n) +# Linux Capabilities +find_library(CAP_LIB cap) +if(CAP_LIB) + target_link_libraries(edge cap) + set(CMAKE_REQUIRED_LIBRARIES ${CAP_LIB}) + ADD_DEFINITIONS("-DHAVE_LIBCAP") +endif() + install(TARGETS edge supernode RUNTIME DESTINATION sbin LIBRARY DESTINATION lib diff --git a/edge_utils.c b/edge_utils.c index 182eb91..c387edc 100644 --- a/edge_utils.c +++ b/edge_utils.c @@ -2063,7 +2063,7 @@ static char* route_cmd_to_str(int cmd, const n2n_route_t *route, char *buf, size /* Adapted from https://olegkutkov.me/2019/08/29/modifying-linux-network-routes-using-netlink/ */ #define NLMSG_TAIL(nmsg) \ - ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) + ((struct rtattr *) (((char *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) /* Add new data to rtattr */ static int rtattr_add(struct nlmsghdr *n, int maxlen, int type, const void *data, int alen) From 3d9d3a13f7f0e4ada2c5861807ed2dce990b6a49 Mon Sep 17 00:00:00 2001 From: emanuele-f Date: Wed, 27 May 2020 10:54:12 +0200 Subject: [PATCH 13/15] Windows cmake fix Fixes #248 --- CMakeLists.txt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fe2319f..8f52c16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,13 +92,15 @@ target_link_libraries(example_edge_embed n2n) add_executable(example_sn_embed example_sn_embed.c) target_link_libraries(example_sn_embed n2n) -# Linux Capabilities -find_library(CAP_LIB cap) -if(CAP_LIB) - target_link_libraries(edge cap) - set(CMAKE_REQUIRED_LIBRARIES ${CAP_LIB}) - ADD_DEFINITIONS("-DHAVE_LIBCAP") -endif() +if(NOT DEFINED WIN32) + # Linux Capabilities + find_library(CAP_LIB cap) + if(CAP_LIB) + target_link_libraries(edge cap) + set(CMAKE_REQUIRED_LIBRARIES ${CAP_LIB}) + ADD_DEFINITIONS("-DHAVE_LIBCAP") + endif() +endif(NOT DEFINED WIN32) install(TARGETS edge supernode RUNTIME DESTINATION sbin From 048b7c7794063e4d8081731b02ac603c28a7b58e Mon Sep 17 00:00:00 2001 From: lishuxiang Date: Sun, 31 May 2020 10:30:15 +0800 Subject: [PATCH 14/15] Fix a typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0ef019e..862232f 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ n2n edge nodes use twofish encryption by default for compatibility reasons with of the edge nodes, their IP address and the community are sent in cleartext. When encryption is enabled, the supernode will not be able to decrypt the traffic exchanged between -two edge nodes, but it will now that edge A is talking with edge B. +two edge nodes, but it will know that edge A is talking with edge B. Recently AES encryption support has been implemented, which increases both security and performance, so it is recommended to enable it on all the edge nodes by specifying the `-A` option. From b8fcf091779468def5493f7db9dc55334c826003 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Sun, 7 Jun 2020 10:00:18 +0200 Subject: [PATCH 15/15] Compilation fixes --- README.md | 3 +- edge.c | 87 ++++++++++++++++++++++++++---------------------- transform_cc20.c | 6 ---- 3 files changed, 50 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 862232f..fb99257 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,8 @@ When encryption is enabled, the supernode will not be able to decrypt the traffi two edge nodes, but it will know that edge A is talking with edge B. Recently AES encryption support has been implemented, which increases both security and performance, -so it is recommended to enable it on all the edge nodes by specifying the `-A` option. +so it is recommended to enable it on all the edge nodes that must have the -Ax value. When possible +(i.e. when n2n is compiled with OpenSSL 1.1) we recommend to use -A4 A benchmark of the encryption methods is available when compiled from source with `tools/n2n-benchmark`. diff --git a/edge.c b/edge.c index da0cd4f..fe2eb41 100644 --- a/edge.c +++ b/edge.c @@ -189,12 +189,12 @@ static void help() { #endif printf("-r | Enable packet forwarding through n2n community.\n"); printf("-A1 | Disable payload encryption. Do not use with -k.\n"); - printf("-A2 | Use Twofish for payload encryption (default). Requires a key.\n"); + printf("-A2 | Use Twofish for payload encryption (default). Requires a key (-k).\n"); #ifdef N2N_HAVE_AES - printf("-A3 or -A (deprecated) | Use AES-CBC for payload encryption. Requires a key.\n"); + printf("-A3 or -A (deprecated) | Use AES-CBC for payload encryption. Requires a key (-k).\n"); #endif #ifdef HAVE_OPENSSL_1_1 - printf("-A4 | Use ChaCha20 for payload encryption. Requires a key.\n"); + printf("-A4 | Use ChaCha20 for payload encryption. Requires a key (-k).\n"); #endif printf("-z | Enable lzo1x compression for outgoing data packets\n"); printf(" | (default=disabled).\n"); @@ -220,6 +220,46 @@ static void help() { /* *************************************************** */ +static void setPayloadEncryption( n2n_edge_conf_t *conf, int cipher) { + /* even though 'cipher' and 'conf->transop_id' share the same encoding scheme, + * a switch-statement under conditional compilation is used to sort out the + * unsupported ciphers */ + switch (cipher) { + case 1: + { + conf->transop_id = N2N_TRANSFORM_ID_NULL; + break; + } + case 2: + { + conf->transop_id = N2N_TRANSFORM_ID_TWOFISH; + break; + } +#ifdef N2N_HAVE_AES + case 3: + { + conf->transop_id = N2N_TRANSFORM_ID_AESCBC; + break; + } +#endif +#ifdef HAVE_OPENSSL_1_1 + case 4: + { + conf->transop_id = N2N_TRANSFORM_ID_CHACHA20; + break; + } +#endif + default: + { + conf->transop_id = N2N_TRANSFORM_ID_INVAL; + traceEvent(TRACE_NORMAL, "the %s cipher given by -A_ option is not supported in this version.", transop_str(cipher)); + exit(1); + } + } +} + +/* *************************************************** */ + static int setOption(int optkey, char *optargument, n2n_priv_config_t *ec, n2n_edge_conf_t *conf) { /* traceEvent(TRACE_NORMAL, "Option %c = %s", optkey, optargument ? optargument : ""); */ @@ -308,48 +348,17 @@ static int setOption(int optkey, char *optargument, n2n_priv_config_t *ec, n2n_e case 'A': { - int cipher = N2N_TRANSFORM_ID_AESCBC; // default, if '-A' only + int cipher; + if (optargument) { cipher = atoi(optargument); } else { traceEvent(TRACE_NORMAL, "the use of the solitary -A switch is deprecated and might not be supported in future versions. " "please use -A3 instead to choose a the AES-CBC cipher for payload encryption."); + cipher = N2N_TRANSFORM_ID_AESCBC; // default, if '-A' only } - /* even though 'cipher' and 'conf->transop_id' share the same encoding scheme, - * a switch-statement under conditional compilation is used to sort out the - * unsupported ciphers */ - switch (cipher) { - case 1: - { - conf->transop_id = N2N_TRANSFORM_ID_NULL; - break; - } - case 2: - { - conf->transop_id = N2N_TRANSFORM_ID_TWOFISH; - break; - } -#ifdef N2N_HAVE_AES - case 3: - { - conf->transop_id = N2N_TRANSFORM_ID_AESCBC; - break; - } -#endif -#ifdef HAVE_OPENSSL_1_1 - case 4: - { - conf->transop_id = N2N_TRANSFORM_ID_CHACHA20; - break; - } -#endif - default: - { - conf->transop_id = N2N_TRANSFORM_ID_INVAL; - traceEvent(TRACE_NORMAL, "the %s cipher given by -A_ option is not supported in this version.", transop_str(cipher)); - exit(1); - } - } + + setPayloadEncryption(conf, cipher); break; } diff --git a/transform_cc20.c b/transform_cc20.c index 389cfe5..f937775 100644 --- a/transform_cc20.c +++ b/transform_cc20.c @@ -120,9 +120,6 @@ static int transop_encode_cc20(n2n_trans_op_t * arg, /* Generate and encode the IV. */ set_cc20_iv(priv, enc_ivec); encode_buf(outbuf, &idx, &enc_ivec, N2N_CC20_IVEC_SIZE); - traceEvent(TRACE_DEBUG, "encode_cc20 iv=%016llx:%016llx", - htobe64(*(uint64_t*)&enc_ivec[0]), - htobe64(*(uint64_t*)&enc_ivec[8]) ); /* Encrypt the assembly contents and write the ciphertext after the iv. */ /* len is set to the length of the cipher plain text to be encrpyted @@ -198,9 +195,6 @@ static int transop_decode_cc20(n2n_trans_op_t * arg, /* Get the IV */ decode_buf((uint8_t *)&dec_ivec, N2N_CC20_IVEC_SIZE, inbuf, &rem, &idx); - traceEvent(TRACE_DEBUG, "decode_cc20 iv=%016llx:%016llx", - htobe64(*(uint64_t*)&dec_ivec[0]), - htobe64(*(uint64_t*)&dec_ivec[8]) ); EVP_CIPHER_CTX *ctx = priv->dec_ctx; int evp_len;