Enforce maximum amount of bytes sent/received on meta-connections.
authorGuus Sliepen <guus@tinc-vpn.org>
Sat, 29 Oct 2016 17:51:35 +0000 (19:51 +0200)
committerGuus Sliepen <guus@tinc-vpn.org>
Sat, 29 Oct 2016 17:51:35 +0000 (19:51 +0200)
This is sqrt(2^{block_length_in_bits}).

src/connection.c
src/connection.h
src/meta.c
src/protocol_auth.c

index fd7ae84..8966d65 100644 (file)
@@ -91,6 +91,8 @@ void free_connection_partially(connection_t *c) {
        c->outbufstart = 0;
        c->last_ping_time = 0;
        c->last_flushed_time = 0;
+       c->inbudget = 0;
+       c->outbudget = 0;
 
        if(c->inctx) {
                EVP_CIPHER_CTX_cleanup(c->inctx);
index d3e9224..0922fbe 100644 (file)
@@ -71,6 +71,8 @@ typedef struct connection_t {
        const EVP_CIPHER *outcipher;    /* Cipher we will use to send data to him */
        EVP_CIPHER_CTX *inctx;          /* Context of encrypted meta data that will come from him to us */
        EVP_CIPHER_CTX *outctx;         /* Context of encrypted meta data that will be sent from us to him */
+       uint64_t inbudget;              /* Encrypted bytes send budget */
+       uint64_t outbudget;             /* Encrypted bytes receive budget */
        char *inkey;                            /* His symmetric meta key + iv */
        char *outkey;                           /* Our symmetric meta key + iv */
        int inkeylength;                        /* Length of his key + iv */
index 06ab96e..63f565f 100644 (file)
@@ -62,6 +62,14 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
 
        /* Add our data to buffer */
        if(c->status.encryptout) {
+               /* Check encryption limits */
+               if(length > c->outbudget) {
+                       ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for encryption to %s (%s)", c->name, c->hostname);
+                       return false;
+               } else {
+                       c->outbudget -= length;
+               }
+
                result = EVP_EncryptUpdate(c->outctx, (unsigned char *)c->outbuf + c->outbufstart + c->outbuflen,
                                &outlen, (unsigned char *)buffer, length);
                if(!result || outlen < length) {
@@ -175,6 +183,14 @@ bool receive_meta(connection_t *c) {
                /* Decrypt */
 
                if(c->status.decryptin && !decrypted) {
+                       /* Check decryption limits */
+                       if(lenin > c->inbudget) {
+                               ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for decryption from %s (%s)", c->name, c->hostname);
+                               return false;
+                       } else {
+                               c->inbudget -= lenin;
+                       }
+
                        result = EVP_DecryptUpdate(c->inctx, (unsigned char *)inbuf, &lenout, (unsigned char *)c->buffer + oldlen, lenin);
                        if(!result || lenout != lenin) {
                                logger(LOG_ERR, "Error while decrypting metadata from %s (%s): %s",
index 46b38eb..ddecbc6 100644 (file)
@@ -195,6 +195,7 @@ bool send_metakey(connection_t *c) {
                        return false;
                }
 
+               c->outbudget = (uint64_t)4 << EVP_CIPHER_key_length(c->outcipher);
                c->status.encryptout = true;
        }
 
@@ -273,6 +274,7 @@ bool metakey_h(connection_t *c) {
                        return false;
                }
 
+               c->inbudget = (uint64_t)4 << EVP_CIPHER_key_length(c->incipher);
                c->status.decryptin = true;
        } else {
                c->incipher = NULL;