Add strict checks to hex to binary conversions.
authorGuus Sliepen <guus@tinc-vpn.org>
Sun, 30 Sep 2012 11:45:47 +0000 (13:45 +0200)
committerGuus Sliepen <guus@tinc-vpn.org>
Sun, 30 Sep 2012 11:45:47 +0000 (13:45 +0200)
The main goal is to catch misuse of the obsolete PrivateKey and PublicKey
statements.

lib/utils.c
lib/utils.h
src/net_setup.c
src/protocol_auth.c
src/protocol_key.c

index 405097bbe3d01c592a05147c6df36422c614af65..3b221f59f0ef731f62b0369314de5964bdf855fd 100644 (file)
@@ -32,11 +32,13 @@ static int charhex2bin(char c) {
                return toupper(c) - 'A' + 10;
 }
 
-
-void hex2bin(char *src, char *dst, int length) {
-       int i;
-       for(i = 0; i < length; i++)
+bool hex2bin(char *src, char *dst, int length) {
+       for(int i = 0; i < length; i++) {
+               if(!isxdigit(src[i * 2]) || !isxdigit(src[i * 2 + 1]))
+                       return false;
                dst[i] = charhex2bin(src[i * 2]) * 16 + charhex2bin(src[i * 2 + 1]);
+       }
+       return true;
 }
 
 void bin2hex(char *src, char *dst, int length) {
index f6ff705274a4e6d96b289e0252cf182a8b12b885..2e4fcf86083154b54399b8e34773d294ca1c9fd2 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef __TINC_UTILS_H__
 #define __TINC_UTILS_H__
 
-extern void hex2bin(char *src, char *dst, int length);
+extern bool hex2bin(char *src, char *dst, int length);
 extern void bin2hex(char *src, char *dst, int length);
 
 #ifdef HAVE_MINGW
index eec438a80879831b1a2416fbdeefa0a9cebf6328..a28ab7ad147c7e3989bba3c3231861028098d1c4 100644 (file)
@@ -66,7 +66,10 @@ bool read_rsa_public_key(connection_t *c) {
        /* First, check for simple PublicKey statement */
 
        if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key)) {
-               BN_hex2bn(&c->rsa_key->n, key);
+               if(BN_hex2bn(&c->rsa_key->n, key) != strlen(key)) {
+                       logger(LOG_ERR, "Invalid PublicKey for %s!", c->name);
+                       return false;
+               }
                BN_hex2bn(&c->rsa_key->e, "FFFF");
                free(key);
                return true;
@@ -169,8 +172,14 @@ static bool read_rsa_private_key(void) {
                }
                myself->connection->rsa_key = RSA_new();
 //             RSA_blinding_on(myself->connection->rsa_key, NULL);
-               BN_hex2bn(&myself->connection->rsa_key->d, key);
-               BN_hex2bn(&myself->connection->rsa_key->n, pubkey);
+               if(BN_hex2bn(&myself->connection->rsa_key->d, key) != strlen(key)) {
+                       logger(LOG_ERR, "Invalid PrivateKey for myself!");
+                       return false;
+               }
+               if(BN_hex2bn(&myself->connection->rsa_key->n, pubkey) != strlen(pubkey)) {
+                       logger(LOG_ERR, "Invalid PublicKey for myself!");
+                       return false;
+               }
                BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
                free(key);
                free(pubkey);
index 0ef546822146d5f8b2b5b329e7277fa8fecb2b68..3bd34a01b5743bcf3ee5d354bf4cfdde7bc5c90a 100644 (file)
@@ -308,7 +308,10 @@ bool metakey_h(connection_t *c) {
 
        /* Convert the challenge from hexadecimal back to binary */
 
-       hex2bin(buffer, buffer, len);
+       if(!hex2bin(buffer, buffer, len)) {
+               logger(LOG_ERR, "Got bad %s from %s(%s): %s", "METAKEY", c->name, c->hostname, "invalid key");
+               return false;
+       }
 
        /* Decrypt the meta key */
 
@@ -426,7 +429,10 @@ bool challenge_h(connection_t *c) {
 
        /* Convert the challenge from hexadecimal back to binary */
 
-       hex2bin(buffer, c->mychallenge, len);
+       if(!hex2bin(buffer, c->mychallenge, len)) {
+               logger(LOG_ERR, "Got bad %s from %s(%s): %s", "CHALLENGE", c->name, c->hostname, "invalid challenge");
+               return false;
+       }
 
        c->allow_request = CHAL_REPLY;
 
@@ -480,7 +486,10 @@ bool chal_reply_h(connection_t *c) {
 
        /* Convert the hash to binary format */
 
-       hex2bin(hishash, hishash, c->outdigest->md_size);
+       if(!hex2bin(hishash, hishash, c->outdigest->md_size)) {
+               logger(LOG_ERR, "Got bad %s from %s(%s): %s", "CHAL_REPLY", c->name, c->hostname, "invalid hash");
+               return false;
+       }
 
        /* Calculate the hash from the challenge we sent */
 
index 1a184fb8f3ba817dccb4553a051361a4bf4b61a9..f2f317de5e9888a6d603a95e148bbde371ec139b 100644 (file)
@@ -240,10 +240,16 @@ bool ans_key_h(connection_t *c) {
                return send_request(to->nexthop->connection, "%s", c->buffer);
        }
 
+       /* Don't use key material until every check has passed. */
+       from->status.validkey = false;
+
        /* Update our copy of the origin's packet key */
        from->outkey = xrealloc(from->outkey, strlen(key) / 2);
        from->outkeylength = strlen(key) / 2;
-       hex2bin(key, from->outkey, from->outkeylength);
+       if(!hex2bin(key, from->outkey, from->outkeylength)) {
+               logger(LOG_ERR, "Got bad %s from %s(%s): %s", "ANS_KEY", from->name, from->hostname, "invalid key");
+               return true;
+       }
 
        /* Check and lookup cipher and digest algorithms */