diff --git a/configure.ac b/configure.ac index cbee626..991c9d3 100644 --- a/configure.ac +++ b/configure.ac @@ -62,7 +62,7 @@ AC_CHECK_LIB([seccomp], [seccomp_init]) # Checks for header files. AC_CHECK_HEADERS([stdlib.h stdio.h unistd.h stdint.h string.h time.h signal.h]) AC_CHECK_HEADERS([syslog.h fcntl.h seccomp.h netdb.h net/if.h netinet/in.h]) -AC_CHECK_HEADERS([sys/types.h sys/stat.h sys/ioctl.h sys/select.h sys/socket.h]) +AC_CHECK_HEADERS([sys/types.h sys/stat.h sys/ioctl.h sys/epoll.h sys/socket.h]) AC_CHECK_HEADERS([grp.h pwd.h]) # Checks for typedefs, structures, and compiler characteristics. @@ -75,7 +75,7 @@ AC_TYPE_UINT64_T # Checks for library functions. AC_FUNC_MALLOC -AC_CHECK_FUNCS([memset select socket]) +AC_CHECK_FUNCS([memset socket]) # Sanity check for configure AC_CONFIG_SRCDIR([src/meshvpn.c]) diff --git a/include/crypto.h b/include/crypto.h index 6e0f9e1..21649ad 100644 --- a/include/crypto.h +++ b/include/crypto.h @@ -47,9 +47,9 @@ // cipher context storage struct s_crypto { - EVP_CIPHER_CTX enc_ctx; - EVP_CIPHER_CTX dec_ctx; - HMAC_CTX hmac_ctx; + EVP_CIPHER_CTX *enc_ctx; + EVP_CIPHER_CTX *dec_ctx; + HMAC_CTX *hmac_ctx; }; @@ -119,4 +119,29 @@ int cryptoCalculateSHA512(unsigned char *hash_buf, const int hash_len, const uns // generate session keys from password int cryptoSetSessionKeysFromPassword(struct s_crypto *session_ctx, const unsigned char *password, const int password_len, const int cipher_algorithm, const int hmac_algorithm); +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#include + +struct ossl_init_settings_st { + char *filename; + char *appname; + unsigned long flags; +}; + +typedef struct ossl_init_settings_st OPENSSL_INIT_SETTINGS; + +# define OPENSSL_INIT_ADD_ALL_CIPHERS 0x00000004L +# define OPENSSL_INIT_ADD_ALL_DIGESTS 0x00000008L +# define OPENSSL_INIT_LOAD_CONFIG 0x00000040L + +void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key); +HMAC_CTX *HMAC_CTX_new(void); +void HMAC_CTX_free(HMAC_CTX *ctx); +EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void); +void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx); +EVP_MD_CTX *EVP_MD_CTX_new(void); +void EVP_MD_CTX_free(EVP_MD_CTX *ctx); +int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); +#endif + #endif diff --git a/include/io.h b/include/io.h index 2d9525d..68844fc 100644 --- a/include/io.h +++ b/include/io.h @@ -61,8 +61,8 @@ #include #include #include -#include #include +#include #endif #if defined(IO_LINUX) @@ -89,55 +89,58 @@ // The IO addr structure. struct s_io_addr { - unsigned char addr[24]; + unsigned char addr[24]; }; // The IO addrinfo structure. struct s_io_addrinfo { - struct s_io_addr item[16]; - int count; + struct s_io_addr item[16]; + int count; }; // The IO handle structure. struct s_io_handle { - int enabled; - int fd; - struct sockaddr_storage source_sockaddr; - struct s_io_addr source_addr; - int group_id; - int content_len; - int type; - int open; + int enabled; + int fd; + struct sockaddr_storage source_sockaddr; + struct s_io_addr source_addr; + int group_id; + int content_len; + int type; + int open; #if defined(IO_WINDOWS) - HANDLE fd_h; - int open_h; - OVERLAPPED ovlr; - int ovlr_used; - OVERLAPPED ovlw; - int ovlw_used; + HANDLE fd_h; + int open_h; + OVERLAPPED ovlr; + int ovlr_used; + OVERLAPPED ovlw; + int ovlw_used; #endif }; // The IO state structure. struct s_io_state { - unsigned char *mem; - struct s_io_handle *handle; - int bufsize; - int max; - int count; - int timeout; - int sockmark; - int nat64clat; - unsigned char nat64_prefix[12]; - int debug; + unsigned char *mem; + struct s_io_handle *handle; + int bufsize; + int max; + int count; + int timeout; + int sockmark; + int nat64clat; + unsigned char nat64_prefix[12]; + int debug; +#if defined(IO_LINUX) || defined(IO_BSD) + int epollfd; +#endif }; // Returns length of string. -int ioStrlen(const char *str, const int max_len); +size_t ioStrlen(const char *str, const size_t max_len); // Resolve name. Returns number of addresses. int ioResolveName(struct s_io_addrinfo *iai, const char *hostname, const char *port); diff --git a/src/app/config.c b/src/app/config.c index 707ca49..99315b3 100644 --- a/src/app/config.c +++ b/src/app/config.c @@ -110,68 +110,68 @@ int parseConfigLine(char *line, int len, struct s_initconfig *cs) { return 1; } else if(parseConfigLineCheckCommand(line,len,"local",&vpos)) { - strncpy(cs->sourceip,&line[vpos],CONFPARSER_NAMEBUF_SIZE); + strncpy(cs->sourceip,&line[vpos],CONFPARSER_NAMEBUF_SIZE+1); return 1; } else if(parseConfigLineCheckCommand(line,len,"port",&vpos)) { - strncpy(cs->sourceport,&line[vpos],CONFPARSER_NAMEBUF_SIZE); + strncpy(cs->sourceport,&line[vpos],CONFPARSER_NAMEBUF_SIZE+1); return 1; } else if(parseConfigLineCheckCommand(line,len,"user",&vpos)) { - strncpy(cs->userstr,&line[vpos],CONFPARSER_NAMEBUF_SIZE); + strncpy(cs->userstr,&line[vpos],CONFPARSER_NAMEBUF_SIZE+1); return 1; } else if(parseConfigLineCheckCommand(line,len,"group",&vpos)) { - strncpy(cs->groupstr,&line[vpos],CONFPARSER_NAMEBUF_SIZE); + strncpy(cs->groupstr,&line[vpos],CONFPARSER_NAMEBUF_SIZE+1); return 1; } else if(parseConfigLineCheckCommand(line, len, "pidfile", &vpos)) { - strncpy(cs->pidfile, &line[vpos],CONFPARSER_NAMEBUF_SIZE); + strncpy(cs->pidfile, &line[vpos],CONFPARSER_NAMEBUF_SIZE+1); cs->enablepidfile = 1; return 1; } else if(parseConfigLineCheckCommand(line, len, "privatekey", &vpos)) { - strncpy(cs->privatekey, &line[vpos], CONFPARSER_NAMEBUF_SIZE); + strncpy(cs->privatekey, &line[vpos], CONFPARSER_NAMEBUF_SIZE+1); return 1; } else if(parseConfigLineCheckCommand(line,len,"chroot",&vpos)) { - strncpy(cs->chrootstr,&line[vpos],CONFPARSER_NAMEBUF_SIZE); + strncpy(cs->chrootstr,&line[vpos],CONFPARSER_NAMEBUF_SIZE+1); return 1; } else if(parseConfigLineCheckCommand(line,len,"networkname",&vpos)) { - strncpy(cs->networkname,&line[vpos],CONFPARSER_NAMEBUF_SIZE); + strncpy(cs->networkname,&line[vpos],CONFPARSER_NAMEBUF_SIZE+1); return 1; } else if(parseConfigLineCheckCommand(line,len,"interface",&vpos)) { - strncpy(cs->tapname,&line[vpos],CONFPARSER_NAMEBUF_SIZE); + strncpy(cs->tapname,&line[vpos],CONFPARSER_NAMEBUF_SIZE+1); return 1; } else if(parseConfigLineCheckCommand(line,len,"ifconfig4",&vpos)) { - strncpy(cs->ifconfig4,&line[vpos],CONFPARSER_NAMEBUF_SIZE); + strncpy(cs->ifconfig4,&line[vpos],CONFPARSER_NAMEBUF_SIZE+1); return 1; } else if(parseConfigLineCheckCommand(line,len,"ifconfig6",&vpos)) { - strncpy(cs->ifconfig6,&line[vpos],CONFPARSER_NAMEBUF_SIZE); + strncpy(cs->ifconfig6,&line[vpos],CONFPARSER_NAMEBUF_SIZE+1); return 1; } else if(parseConfigLineCheckCommand(line,len,"upcmd",&vpos)) { - strncpy(cs->upcmd,&line[vpos],CONFPARSER_NAMEBUF_SIZE); + strncpy(cs->upcmd,&line[vpos],CONFPARSER_NAMEBUF_SIZE+1); return 1; } else if(parseConfigLineCheckCommand(line,len,"initpeers",&vpos)) { - cs->initpeers[cs->initpeerscount] = malloc(sizeof(char) * CONFPARSER_NAMEBUF_SIZE); - strncpy(cs->initpeers[cs->initpeerscount],&line[vpos],CONFPARSER_NAMEBUF_SIZE); + cs->initpeers[cs->initpeerscount] = malloc(sizeof(char) * (CONFPARSER_NAMEBUF_SIZE+1)); + strncpy(cs->initpeers[cs->initpeerscount],&line[vpos],CONFPARSER_NAMEBUF_SIZE+1); cs->initpeerscount++; debug("detected new init peers"); return 1; } else if(parseConfigLineCheckCommand(line,len,"engine",&vpos)) { - strncpy(cs->engines,&line[vpos],CONFPARSER_NAMEBUF_SIZE); + strncpy(cs->engines,&line[vpos],CONFPARSER_NAMEBUF_SIZE+1); return 1; } else if(parseConfigLineCheckCommand(line,len,"psk",&vpos)) { - strncpy(cs->password,&line[vpos],CONFPARSER_NAMEBUF_SIZE); + strncpy(cs->password,&line[vpos],CONFPARSER_NAMEBUF_SIZE+1); cs->password_len = strlen(cs->password); return 1; } diff --git a/src/encryption/crypto.c b/src/encryption/crypto.c index 859c554..38a2a3e 100644 --- a/src/encryption/crypto.c +++ b/src/encryption/crypto.c @@ -137,44 +137,44 @@ int cryptoSetKeys(struct s_crypto *ctxs, const int count, const unsigned char *s const EVP_MD *out_md = EVP_sha256(); const EVP_CIPHER *out_cipher = EVP_aes_256_cbc(); const int key_size = EVP_CIPHER_key_length(out_cipher); - HMAC_CTX hmac_ctx; + HMAC_CTX *hmac_ctx; int16_t i; unsigned char in[2]; int j,k; // setup hmac as the pseudorandom function - HMAC_CTX_init(&hmac_ctx); + hmac_ctx = HMAC_CTX_new(); // calculate seed key - HMAC_Init_ex(&hmac_ctx, nonce_buf, nonce_len, keygen_md, NULL); - HMAC_Update(&hmac_ctx, secret_buf, secret_len); - HMAC_Final(&hmac_ctx, seed_key, (unsigned int *)&seed_key_len); + HMAC_Init_ex(hmac_ctx, nonce_buf, nonce_len, keygen_md, NULL); + HMAC_Update(hmac_ctx, secret_buf, secret_len); + HMAC_Final(hmac_ctx, seed_key, (unsigned int *)&seed_key_len); // calculate derived keys - HMAC_Init_ex(&hmac_ctx, seed_key, seed_key_len, keygen_md, NULL); - HMAC_Update(&hmac_ctx, nonce_buf, nonce_len); - HMAC_Final(&hmac_ctx, cur_key, (unsigned int *)&cur_key_len); + HMAC_Init_ex(hmac_ctx, seed_key, seed_key_len, keygen_md, NULL); + HMAC_Update(hmac_ctx, nonce_buf, nonce_len); + HMAC_Final(hmac_ctx, cur_key, (unsigned int *)&cur_key_len); i = 0; j = 0; k = 0; while(k < count) { // calculate next key utilWriteInt16(in, i); - HMAC_Init_ex(&hmac_ctx, NULL, -1, NULL, NULL); - HMAC_Update(&hmac_ctx, cur_key, cur_key_len); - HMAC_Update(&hmac_ctx, nonce_buf, nonce_len); - HMAC_Update(&hmac_ctx, in, 2); - HMAC_Final(&hmac_ctx, cur_key, (unsigned int *)&cur_key_len); + HMAC_Init_ex(hmac_ctx, NULL, -1, NULL, NULL); + HMAC_Update(hmac_ctx, cur_key, cur_key_len); + HMAC_Update(hmac_ctx, nonce_buf, nonce_len); + HMAC_Update(hmac_ctx, in, 2); + HMAC_Final(hmac_ctx, cur_key, (unsigned int *)&cur_key_len); if(cur_key_len < key_size) return 0; // check if key is long enough switch(j) { case 1: // save this key as the decryption and encryption key - if(!EVP_EncryptInit_ex(&ctxs[k].enc_ctx, out_cipher, NULL, cur_key, NULL)) return 0; - if(!EVP_DecryptInit_ex(&ctxs[k].dec_ctx, out_cipher, NULL, cur_key, NULL)) return 0; + if(!EVP_EncryptInit_ex(ctxs[k].enc_ctx, out_cipher, NULL, cur_key, NULL)) return 0; + if(!EVP_DecryptInit_ex(ctxs[k].dec_ctx, out_cipher, NULL, cur_key, NULL)) return 0; break; case 2: // save this key as the hmac key - HMAC_Init_ex(&ctxs[k].hmac_ctx, cur_key, cur_key_len, out_md, NULL); + HMAC_Init_ex(ctxs[k].hmac_ctx, cur_key, cur_key_len, out_md, NULL); break; default: // throw this key away @@ -189,7 +189,7 @@ int cryptoSetKeys(struct s_crypto *ctxs, const int count, const unsigned char *s } // clean up - HMAC_CTX_cleanup(&hmac_ctx); + HMAC_CTX_free(hmac_ctx); return 1; } @@ -209,9 +209,9 @@ void cryptoDestroy(struct s_crypto *ctxs, const int count) { int i; cryptoSetKeysRandom(ctxs, count); for(i=0; ihmac_ctx, NULL, -1, NULL, NULL); - HMAC_Update(&ctx->hmac_ctx, in_buf, in_len); - HMAC_Final(&ctx->hmac_ctx, hmac, (unsigned int *)&len); + HMAC_Init_ex(ctx->hmac_ctx, NULL, -1, NULL, NULL); + HMAC_Update(ctx->hmac_ctx, in_buf, in_len); + HMAC_Final(ctx->hmac_ctx, hmac, (unsigned int *)&len); if(len < hmac_len) return 0; memcpy(hmac_buf, hmac, hmac_len); return 1; @@ -270,9 +270,9 @@ int cryptoSetSessionKeys(struct s_crypto *session_ctx, struct s_crypto *cipher_k if(!cryptoHMAC(md_keygen_ctx, hmac_key, key_size, nonce, nonce_len)) return 0; // set the keys - if(!EVP_EncryptInit_ex(&session_ctx->enc_ctx, st_cipher.cipher, NULL, cipher_key, NULL)) return 0; - if(!EVP_DecryptInit_ex(&session_ctx->dec_ctx, st_cipher.cipher, NULL, cipher_key, NULL)) return 0; - HMAC_Init_ex(&session_ctx->hmac_ctx, hmac_key, key_size, st_md.md, NULL); + if(!EVP_EncryptInit_ex(session_ctx->enc_ctx, st_cipher.cipher, NULL, cipher_key, NULL)) return 0; + if(!EVP_DecryptInit_ex(session_ctx->dec_ctx, st_cipher.cipher, NULL, cipher_key, NULL)) return 0; + HMAC_Init_ex(session_ctx->hmac_ctx, hmac_key, key_size, st_md.md, NULL); return 1; } @@ -294,10 +294,10 @@ int cryptoEnc(struct s_crypto *ctx, unsigned char *enc_buf, const int enc_len, c cryptoRand(iv, iv_len); memcpy(&enc_buf[hmac_len], iv, iv_len); - if(!EVP_EncryptInit_ex(&ctx->enc_ctx, NULL, NULL, NULL, iv)) { return 0; } - if(!EVP_EncryptUpdate(&ctx->enc_ctx, &enc_buf[(hdr_len)], &len, dec_buf, dec_len)) { return 0; } + if(!EVP_EncryptInit_ex(ctx->enc_ctx, NULL, NULL, NULL, iv)) { return 0; } + if(!EVP_EncryptUpdate(ctx->enc_ctx, &enc_buf[(hdr_len)], &len, dec_buf, dec_len)) { return 0; } cr_len = len; - if(!EVP_EncryptFinal(&ctx->enc_ctx, &enc_buf[(hdr_len + cr_len)], &len)) { return 0; } + if(!EVP_EncryptFinal(ctx->enc_ctx, &enc_buf[(hdr_len + cr_len)], &len)) { return 0; } cr_len += len; if(!cryptoHMAC(ctx, hmac, hmac_len, &enc_buf[hmac_len], (iv_len + cr_len))) { return 0; } @@ -325,10 +325,10 @@ int cryptoDec(struct s_crypto *ctx, unsigned char *dec_buf, const int dec_len, c memset(iv, 0, crypto_MAXIVSIZE); memcpy(iv, &enc_buf[hmac_len], iv_len); - if(!EVP_DecryptInit_ex(&ctx->dec_ctx, NULL, NULL, NULL, iv)) { return 0; } - if(!EVP_DecryptUpdate(&ctx->dec_ctx, dec_buf, &len, &enc_buf[hdr_len], (enc_len - hdr_len))) { return 0; } + if(!EVP_DecryptInit_ex(ctx->dec_ctx, NULL, NULL, NULL, iv)) { return 0; } + if(!EVP_DecryptUpdate(ctx->dec_ctx, dec_buf, &len, &enc_buf[hdr_len], (enc_len - hdr_len))) { return 0; } cr_len = len; - if(!EVP_DecryptFinal(&ctx->dec_ctx, &dec_buf[cr_len], &len)) { return 0; } + if(!EVP_DecryptFinal(ctx->dec_ctx, &dec_buf[cr_len], &len)) { return 0; } cr_len += len; return cr_len; @@ -340,11 +340,11 @@ int cryptoCalculateHash(unsigned char *hash_buf, const int hash_len, const unsig unsigned char hash[EVP_MAX_MD_SIZE]; int len; EVP_MD_CTX *ctx; - ctx = EVP_MD_CTX_create(); + ctx = EVP_MD_CTX_new(); EVP_DigestInit_ex(ctx, hash_func, NULL); EVP_DigestUpdate(ctx, in_buf, in_len); EVP_DigestFinal(ctx, hash, (unsigned int *)&len); - EVP_MD_CTX_destroy(ctx); + EVP_MD_CTX_free(ctx); if(len < hash_len) return 0; memcpy(hash_buf, hash, hash_len); return 1; @@ -389,6 +389,71 @@ int cryptoSetSessionKeysFromPassword(struct s_crypto *session_ctx, const unsigne return ret_b; } +#if OPENSSL_VERSION_NUMBER < 0x10100000L +void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) { + if (pub_key != NULL) + *pub_key = dh->pub_key; + if (priv_key != NULL) + *priv_key = dh->priv_key; +} + +HMAC_CTX *HMAC_CTX_new(void) { + HMAC_CTX *ctx = OPENSSL_malloc(sizeof(*ctx)); + if (ctx != NULL) { + HMAC_CTX_init(ctx); + } + return ctx; +} + +void HMAC_CTX_free(HMAC_CTX *ctx) { + if (ctx != NULL) { + HMAC_CTX_cleanup(ctx); + OPENSSL_free(ctx); + } +} + +EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void) { + EVP_CIPHER_CTX *ctx = OPENSSL_malloc(sizeof(*ctx)); + if (ctx != NULL) { + EVP_CIPHER_CTX_init(ctx); + } + return ctx; +} + +void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) { + if (ctx != NULL) { + EVP_CIPHER_CTX_cleanup(ctx); + OPENSSL_free(ctx); + } +} + +EVP_MD_CTX *EVP_MD_CTX_new(void) { + return EVP_MD_CTX_create(); +} +void EVP_MD_CTX_free(EVP_MD_CTX *ctx) { + EVP_MD_CTX_destroy(ctx); +} + +int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) { + switch (opts) { + case OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS | OPENSSL_INIT_LOAD_CONFIG: + OPENSSL_add_all_algorithms_conf(); + break; + case OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS: + OPENSSL_add_all_algorithms_noconf(); + break; + case OPENSSL_INIT_ADD_ALL_CIPHERS: + OpenSSL_add_all_ciphers(); + break; + case OPENSSL_INIT_ADD_ALL_DIGESTS: + OpenSSL_add_all_digests(); + break; + default: + return 0; + } + return 1; +} +#endif #endif // F_CRYPTO_C diff --git a/src/encryption/dh.c b/src/encryption/dh.c index f6000cf..a8009dc 100644 --- a/src/encryption/dh.c +++ b/src/encryption/dh.c @@ -70,10 +70,10 @@ CXzWzPkElg5L22pMUCPfYxo10HKoUHmSYwIBAg==\n\ // Generate a key. int dhGenKey(struct s_dh_state *dhstate) { - BIGNUM *bn; + const BIGNUM *bn; int bn_size; if(DH_generate_key(dhstate->dh)) { - bn = dhstate->dh->pub_key; + DH_get0_key(dhstate->dh, &bn, NULL); bn_size = BN_num_bytes(bn); if((bn_size > dh_MINSIZE) && (bn_size < dh_MAXSIZE)) { BN_bn2bin(bn, dhstate->pubkey); @@ -141,13 +141,15 @@ int dhGetPubkey(unsigned char *buf, const int buf_size, const struct s_dh_state // Generate symmetric keys. Returns 1 if succesful. int dhGenCryptoKeys(struct s_crypto *ctx, const int ctx_count, const struct s_dh_state *dhstate, const unsigned char *peerkey, const int peerkey_len, const unsigned char *nonce, const int nonce_len) { BIGNUM *bn = dhstate->bn; + const BIGNUM *bn2; DH *dh = dhstate->dh; int ret = 0; int maxsize = DH_size(dh); unsigned char secret[maxsize]; int size; BN_bin2bn(peerkey, peerkey_len, bn); - if(BN_ucmp(bn, dh->pub_key) != 0) { + DH_get0_key(dh, &bn2, NULL); + if(BN_ucmp(bn, bn2) != 0) { size = DH_compute_key(secret, bn, dh); if(size > 0) { ret = cryptoSetKeys(ctx, ctx_count, secret, size, nonce, nonce_len); diff --git a/src/encryption/rsa.c b/src/encryption/rsa.c index 8fd714f..b2c1506 100644 --- a/src/encryption/rsa.c +++ b/src/encryption/rsa.c @@ -98,7 +98,7 @@ int rsaGetFingerprint(unsigned char *buf, const int buf_size, const struct s_rsa * keypath should be accessable */ int rsaImportKey(struct s_rsa * rsa, const char *keypath) { - OpenSSL_add_all_algorithms(); + OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL); BIO * in; RSA * rsakey; @@ -328,7 +328,7 @@ int rsaCreate(struct s_rsa *rsa) { BN_zero(rsa->bn); rsa->key = EVP_PKEY_new(); if(rsa->key != NULL) { - rsa->md = EVP_MD_CTX_create(); + rsa->md = EVP_MD_CTX_new(); if(rsa->md != NULL) { rsaReset(rsa); return 1; @@ -342,7 +342,7 @@ int rsaCreate(struct s_rsa *rsa) { // Destroy a RSA object. void rsaDestroy(struct s_rsa *rsa) { rsaReset(rsa); - EVP_MD_CTX_destroy(rsa->md); + EVP_MD_CTX_free(rsa->md); EVP_PKEY_free(rsa->key); BN_free(rsa->bn); } diff --git a/src/p2p/p2psec.c b/src/p2p/p2psec.c index 7d0f81b..3ab5990 100644 --- a/src/p2p/p2psec.c +++ b/src/p2p/p2psec.c @@ -289,7 +289,7 @@ void p2psecDisableRelay(struct s_p2psec *p2psec) { int p2psecLoadDefaults(struct s_p2psec *p2psec) { if(!p2psecLoadDH(p2psec)) return 0; p2psecSetFlag(p2psec, (~(0)), 0); - p2psecSetMaxConnectedPeers(p2psec, 256); + p2psecSetMaxConnectedPeers(p2psec, 65536); p2psecSetAuthSlotCount(p2psec, 32); p2psecDisableLoopback(p2psec); p2psecEnableFastauth(p2psec); diff --git a/src/p2p/peeraddr.c b/src/p2p/peeraddr.c index 702b777..0e65268 100644 --- a/src/p2p/peeraddr.c +++ b/src/p2p/peeraddr.c @@ -27,6 +27,7 @@ #include "string.h" #include #include "p2p.h" +#include "io.h" // Returns true if PeerAddr is internal. @@ -89,7 +90,11 @@ void peeraddrSetIndirect(struct s_peeraddr *peeraddr, const int relayid, const i */ void peeraddrToHuman(char * buffer, const struct s_peeraddr * peeraddr) { char res[64]; - inet_ntop(AF_INET, &peeraddr->addr[4], res, 64); + if(memcmp(&peeraddr->addr[0], IO_ADDRTYPE_UDP6, 4) == 0) { + inet_ntop(AF_INET6, &peeraddr->addr[4], res, 64); + } else { + inet_ntop(AF_INET, &peeraddr->addr[4], res, 64); + } if(peeraddrGetInternalType(peeraddr) == peeraddr_INTERNAL_INDIRECT) { strcpy(buffer, "INDIRECT"); diff --git a/src/platform/io.c b/src/platform/io.c index b0024e3..755c6cb 100644 --- a/src/platform/io.c +++ b/src/platform/io.c @@ -30,15 +30,15 @@ #include #include #include "logging.h" - +#include "errno.h" #if defined(IO_LINUX) || defined(IO_BSD) #include #include #include #include -#include #include +#include #endif #if defined(IO_LINUX) @@ -53,77 +53,55 @@ // Returns length of string. -int ioStrlen(const char *str, const int max_len) { - int len; - len = 0; - if(str != NULL) { - while(len < max_len && str[len] != '\0') { - len++; - } +size_t ioStrlen(const char *str, const size_t max_len) { + if (str == NULL) { + return 0; } - return len; + return strnlen(str, max_len); } // Resolve name. Returns number of addresses. int ioResolveName(struct s_io_addrinfo *iai, const char *hostname, const char *port) { - int ret; struct s_io_addr *iaiaddr; struct sockaddr_in6 *saddr6; struct sockaddr_in *saddr4; - struct addrinfo *d; - struct addrinfo *di; + struct addrinfo *d, *di; struct addrinfo hints; - - ret = 0; - debugf("Trying to resolve %s", hostname); - + int ret = 0; + debugf("Trying to resolve %s", hostname); if(hostname != NULL && port != NULL) { memset(&hints,0,sizeof(struct addrinfo)); - - hints.ai_family = AF_INET6; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = 0; - d = NULL; - if(getaddrinfo(hostname, port, &hints, &d) == 0) { - di = d; - while(di != NULL && ret < 12) { - saddr6 = (struct sockaddr_in6 *)di->ai_addr; - iaiaddr = &iai->item[ret]; - memcpy(&iaiaddr->addr[0], IO_ADDRTYPE_UDP6, 4); // set address type - memcpy(&iaiaddr->addr[4], saddr6->sin6_addr.s6_addr, 16); // copy IPv6 address - memcpy(&iaiaddr->addr[20], &saddr6->sin6_port, 2); // copy port - memcpy(&iaiaddr->addr[22], "\x00\x00", 2); // empty bytes - di = di->ai_next; - ret++; - } - freeaddrinfo(d); - } - - hints.ai_family = AF_INET; + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = 0; d = NULL; if(getaddrinfo(hostname, port, &hints, &d) == 0) { - di = d; - while(di != NULL && ret < 16) { - saddr4 = (struct sockaddr_in *)di->ai_addr; + for (di = d; di != NULL; di = di->ai_next) { + if (ret >= 16) { + break; + } iaiaddr = &iai->item[ret]; - memcpy(&iaiaddr->addr[0], IO_ADDRTYPE_UDP4, 4); // set address type - memcpy(&iaiaddr->addr[4], &saddr4->sin_addr.s_addr, 4); // copy IPv4 address - memcpy(&iaiaddr->addr[8], &saddr4->sin_port, 2); // copy port - memcpy(&iaiaddr->addr[10], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 14); // empty bytes - di = di->ai_next; + if (di->ai_family == AF_INET6) { + saddr6 = (struct sockaddr_in6 *)di->ai_addr; + memcpy(&iaiaddr->addr[0], IO_ADDRTYPE_UDP6, 4); // set address type + memcpy(&iaiaddr->addr[4], saddr6->sin6_addr.s6_addr, 16); // copy IPv6 address + memcpy(&iaiaddr->addr[20], &saddr6->sin6_port, 2); // copy port + memcpy(&iaiaddr->addr[22], "\x00\x00", 2); // empty bytes + } else { + saddr4 = (struct sockaddr_in *)di->ai_addr; + iaiaddr = &iai->item[ret]; + memcpy(&iaiaddr->addr[0], IO_ADDRTYPE_UDP4, 4); // set address type + memcpy(&iaiaddr->addr[4], &saddr4->sin_addr.s_addr, 4); // copy IPv4 address + memcpy(&iaiaddr->addr[8], &saddr4->sin_port, 2); // copy port + memcpy(&iaiaddr->addr[10], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 14); // empty bytes + } ret++; } freeaddrinfo(d); } - } - - - - debugf("Resolved total %d addresses", ret); + debugf("Resolved total %d addresses", ret); iai->count = ret; return ret; } @@ -193,6 +171,9 @@ void ioClose(struct s_io_state *iostate, const int id) { if(id >= 0 && id < iostate->max) { if(iostate->handle[id].enabled) { if(iostate->handle[id].open) { +#if defined(IO_LINUX) || defined(IO_BSD) + epoll_ctl(iostate->epollfd, EPOLL_CTL_DEL, iostate->handle[id].fd, NULL); +#endif close(iostate->handle[id].fd); iostate->handle[id].open = 0; } @@ -210,16 +191,12 @@ void ioClose(struct s_io_state *iostate, const int id) { // Opens a socket. Returns handle ID if successful, or -1 on error. int ioOpenSocket(struct s_io_state *iostate, const int iotype, const char *bindaddress, const char *bindport, const int domain, const int type, const int protocol) { - int id; - int sockfd; - - int so; - int fd; + int id = -1; + int fd, sockfd = -1; + int so = 1; const char *zero_c = "0"; - const char *useport; - const char *useaddr; - struct addrinfo *d; - struct addrinfo *di; + const char *useport, *useaddr; + struct addrinfo *d, *di = NULL; struct addrinfo hints; #if defined(IO_LINUX) || defined(IO_BSD) @@ -233,7 +210,6 @@ int ioOpenSocket(struct s_io_state *iostate, const int iotype, const char *binda } #if defined(AF_INET6) && defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) - so = 1; if(domain == AF_INET6) { setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&so, sizeof(int)); } @@ -274,51 +250,53 @@ int ioOpenSocket(struct s_io_state *iostate, const int iotype, const char *binda hints.ai_socktype = type; hints.ai_protocol = protocol; hints.ai_flags = AI_PASSIVE; + if(ioStrlen(bindaddress, 255) > 0) { useaddr = bindaddress; - } - else { + } else { useaddr = NULL; } + if(ioStrlen(bindport, 255) > 0) { useport = bindport; - } - else { + } else { useport = zero_c; } - d = NULL; - di = NULL; if(getaddrinfo(useaddr, useport, &hints, &d) != 0) { close(fd); return -1; } - - di = d; - sockfd = -1; - while(di != NULL) { + for (di = d; di != NULL; di = di->ai_next) { if(bind(fd, di->ai_addr, di->ai_addrlen) == 0) { sockfd = fd; break; } - di = di->ai_next; } freeaddrinfo(d); - - if(sockfd < 0) { + if (sockfd < 0) { close(fd); return -1; } - if((id = ioAllocID(iostate)) < 0) { - close(fd); + id = ioAllocID(iostate); + if (id < 0) { + debugf("Unable to open a new io socket, id pool exhausted."); return -1; } +#if defined(IO_LINUX) || defined(IO_BSD) + struct epoll_event event = {0}; + event.data.fd = id; //This is not a real fd but our internal id, we use it to allow for fast data lookup after epoll_wait. + event.events |= EPOLLIN; + if (epoll_ctl(iostate->epollfd, EPOLL_CTL_ADD, fd, &event) < 0) { + close(fd); + return -1; + } +#endif iostate->handle[id].fd = sockfd; iostate->handle[id].type = iotype; iostate->handle[id].open = 1; - return id; } @@ -522,16 +500,12 @@ HANDLE ioOpenTAPWINHandle(char *tapname, const char *reqname, const int reqname_ // Opens a TAP device. Returns handle ID if succesful, or -1 on error. int ioOpenTAP(struct s_io_state *iostate, char *tapname, const char *reqname) { - int id; - int tapfd; + int id = -1; + int tapfd = -1; char filename[512]; + int req_len = ioStrlen(reqname, 255); int name_len; - int req_len; - - req_len = ioStrlen(reqname, 255); memset(filename, 0, 512); - id = -1; - tapfd = -1; #if defined(IO_LINUX) @@ -665,6 +639,16 @@ int ioOpenTAP(struct s_io_state *iostate, char *tapname, const char *reqname) { #endif +#if defined(IO_LINUX) || defined(IO_BSD) + struct epoll_event event = {0}; + event.data.fd = id; //This is not a real fd but our internal id, we use it to allow for fast data lookup after epoll_wait. + event.events |= EPOLLIN; + if (epoll_ctl(iostate->epollfd, EPOLL_CTL_ADD, tapfd, &event) < 0) { + close(tapfd); + return -1; + } +#endif + iostate->handle[id].fd = tapfd; iostate->handle[id].type = IO_TYPE_FILE; return id; @@ -699,6 +683,14 @@ int ioOpenTAP(struct s_io_state *iostate, char *tapname, const char *reqname) { #endif +#if defined(IO_LINUX) || defined(IO_BSD) + struct epoll_event event = {0}; + event.data.fd = id; //This is not a real fd but our internal id, we use it to allow for fast data lookup after epoll_wait. + event.events |= EPOLLIN; + if (epoll_ctl(iostate->epollfd, EPOLL_CTL_ADD, STDIN_FILENO, &event) < 0) { + return -1; + } +#endif return id; } @@ -749,7 +741,7 @@ int ioOpenTAP(struct s_io_state *iostate, char *tapname, const char *reqname) { #if defined(IO_WINDOWS) // Finish receiving an UDP packet. Returns amount of bytes read, or 0 if nothing is read. - int ioHelperFinishRecvFrom(struct s_io_handle *handle) { +int ioHelperFinishRecvFrom(struct s_io_handle *handle) { DWORD len; DWORD flags; @@ -782,7 +774,7 @@ int ioOpenTAP(struct s_io_state *iostate, char *tapname, const char *reqname) { // Sends an UDP packet. Returns length of sent message. - int ioHelperSendTo(struct s_io_handle *handle, const unsigned char *send_buf, const int send_buf_size, const struct sockaddr *destination_sockaddr, const socklen_t destination_sockaddr_len) { +int ioHelperSendTo(struct s_io_handle *handle, const unsigned char *send_buf, const int send_buf_size, const struct sockaddr *destination_sockaddr, const socklen_t destination_sockaddr_len) { int len; #if defined(IO_LINUX) || defined(IO_BSD) @@ -1015,39 +1007,18 @@ int ioReadAll(struct s_io_state *iostate) { #if defined(IO_LINUX) || defined(IO_BSD) - fd_set fdset; - struct timeval seltimeout; - int fd, fdh; - - seltimeout.tv_sec = iostate->timeout; - seltimeout.tv_usec = 0; - - fdh = 0; - FD_ZERO(&fdset); - for(i=0; imax; i++) { - if(iostate->handle[i].enabled) { - fd = iostate->handle[i].fd; - FD_SET(fd, &fdset); - if(fdh < (fd+1)) { - fdh = (fd+1); - } - } + struct epoll_event* events = calloc(64, sizeof(struct epoll_event)); + if(events == NULL) { + return -1; } - - ret = 0; - if(!(fdh < 0)) { - if(select(fdh, &fdset, NULL, NULL, &seltimeout) > 0) { - for(i=0; imax; i++) { - if(iostate->handle[i].enabled) { - if(FD_ISSET(iostate->handle[i].fd, &fdset)) { - ioPreRead(iostate, i); - if(ioRead(iostate, i) > 0) { - ret++; - } - } - } - } - } + ret = epoll_wait(iostate->epollfd, events, 64, iostate->timeout * 1000); + if (ret < 0) { + debugf("epoll_wait failed, error: '%s' [%d]", strerror(errno), errno); + return -1; + } + for (i = 0; i < ret; ++i) { + ioPreRead(iostate, events[i].data.fd); + ioRead(iostate, events[i].data.fd); } #elif defined(IO_WINDOWS) @@ -1300,9 +1271,16 @@ void ioReset(struct s_io_state *iostate) { // Create IO state structure. Returns 1 on success. int ioCreate(struct s_io_state *iostate, const int io_bufsize, const int io_max) { -#ifdef IO_WINDOWS +#if defined(IO_WINDOWS) WSADATA wsadata; - if(WSAStartup(MAKEWORD(2,2), &wsadata) != 0) { return 0; } + if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0) { + return 0; + } +#elif defined(IO_LINUX) || defined(IO_BSD) + iostate->epollfd = epoll_create1(0); + if (iostate->epollfd == -1) { + debugf("epoll_create1 failed, error: '%s' [%d]", strerror(errno), errno); + } #endif if((io_bufsize > 0) && (io_max > 0)) { // check parameters @@ -1332,7 +1310,7 @@ void ioDestroy(struct s_io_state *iostate) { iostate->max = 0; iostate->count = 0; -#ifdef IO_WINDOWS +#if defined(IO_WINDOWS) WSACleanup(); #endif }