Merge branch 'master' into 1.1
authorGuus Sliepen <guus@tinc-vpn.org>
Sun, 30 Sep 2012 13:00:47 +0000 (15:00 +0200)
committerGuus Sliepen <guus@tinc-vpn.org>
Sun, 30 Sep 2012 13:00:47 +0000 (15:00 +0200)
Conflicts:
lib/utils.c
src/net_setup.c
src/process.c
src/protocol_auth.c
src/protocol_key.c
src/utils.h

1  2 
THANKS
src/net_setup.c
src/openssl/rsa.c
src/process.c
src/protocol_key.c
src/tincd.c
src/utils.c

diff --cc THANKS
Simple merge
diff --cc src/net_setup.c
@@@ -214,28 -162,32 +214,28 @@@ static bool read_ecdsa_private_key(void
  
  static bool read_rsa_private_key(void) {
        FILE *fp;
 -      char *fname, *key, *pubkey;
 -      struct stat s;
 +      char *fname;
 +      char *n, *d;
 +      bool result;
  
 -      if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key)) {
 -              if(!get_config_string(lookup_config(config_tree, "PublicKey"), &pubkey)) {
 -                      logger(LOG_ERR, "PrivateKey used but no PublicKey found!");
 -                      return false;
 -              }
 -              myself->connection->rsa_key = RSA_new();
 -//            RSA_blinding_on(myself->connection->rsa_key, NULL);
 -              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!");
 +      /* First, check for simple PrivateKey statement */
 +
 +      if(get_config_string(lookup_config(config_tree, "PrivateKey"), &d)) {
 +              if(!get_config_string(lookup_config(config_tree, "PublicKey"), &n)) {
 +                      logger(DEBUG_ALWAYS, LOG_ERR, "PrivateKey used but no PublicKey found!");
 +                      free(d);
                        return false;
                }
 -              BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
 -              free(key);
 -              free(pubkey);
 -              return true;
 +              result = rsa_set_hex_private_key(&myself->connection->rsa, n, "FFFF", d);
 +              free(n);
 +              free(d);
-               return true;
++              return result;
        }
  
 +      /* Else, check for PrivateKeyFile statement and read it */
 +
        if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname))
 -              xasprintf(&fname, "%s/rsa_key.priv", confbase);
 +              xasprintf(&fname, "%s" SLASH "rsa_key.priv", confbase);
  
        fp = fopen(fname, "r");
  
index 9c880e6,0000000..efd63d5
mode 100644,000000..100644
--- /dev/null
@@@ -1,101 -1,0 +1,106 @@@
-       BN_hex2bn(&(*rsa)->n, n);
-       BN_hex2bn(&(*rsa)->e, e);
 +/*
 +    rsa.c -- RSA key handling
 +    Copyright (C) 2007 Guus Sliepen <guus@tinc-vpn.org>
 +
 +    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 2 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, write to the Free Software Foundation, Inc.,
 +    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 +*/
 +
 +#include "system.h"
 +
 +#include <openssl/pem.h>
 +#include <openssl/err.h>
 +
 +#include "logger.h"
 +#include "rsa.h"
 +
 +// Set RSA keys
 +
 +bool rsa_set_hex_public_key(rsa_t *rsa, char *n, char *e) {
 +      *rsa = RSA_new();
-       BN_hex2bn(&(*rsa)->n, n);
-       BN_hex2bn(&(*rsa)->e, e);
-       BN_hex2bn(&(*rsa)->d, d);
++      if(BN_hex2bn(&(*rsa)->n, n) != strlen(n))
++              return false;
++      if(BN_hex2bn(&(*rsa)->e, e) != strlen(e))
++              return false;
 +      return true;
 +}
 +
 +bool rsa_set_hex_private_key(rsa_t *rsa, char *n, char *e, char *d) {
 +      *rsa = RSA_new();
++      if(BN_hex2bn(&(*rsa)->n, n) != strlen(n))
++              return false;
++      if(BN_hex2bn(&(*rsa)->e, e) != strlen(e))
++              return false;
++      if(BN_hex2bn(&(*rsa)->d, d) != strlen(d))
++              return false;
 +      return true;
 +}
 +
 +// Read PEM RSA keys
 +
 +bool rsa_read_pem_public_key(rsa_t *rsa, FILE *fp) {
 +      *rsa = PEM_read_RSAPublicKey(fp, rsa, NULL, NULL);
 +
 +      if(*rsa)
 +              return true;
 +      
 +      *rsa = PEM_read_RSA_PUBKEY(fp, rsa, NULL, NULL);
 +
 +      if(*rsa)
 +              return true;
 +
 +      logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA public key: %s", ERR_error_string(ERR_get_error(), NULL));
 +      return false;
 +}
 +
 +bool rsa_read_pem_private_key(rsa_t *rsa, FILE *fp) {
 +      *rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
 +
 +      if(*rsa)
 +              return true;
 +      
 +      logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA private key: %s", ERR_error_string(ERR_get_error(), NULL));
 +      return false;
 +}
 +
 +size_t rsa_size(rsa_t *rsa) {
 +      return RSA_size(*rsa);
 +}
 +
 +bool rsa_public_encrypt(rsa_t *rsa, void *in, size_t len, void *out) {
 +      if(RSA_public_encrypt(len, in, out, *rsa, RSA_NO_PADDING) == len)
 +              return true;
 +
 +      logger(DEBUG_ALWAYS, LOG_ERR, "Unable to perform RSA encryption: %s", ERR_error_string(ERR_get_error(), NULL));
 +      return false;   
 +}
 +
 +bool rsa_private_decrypt(rsa_t *rsa, void *in, size_t len, void *out) {
 +      if(RSA_private_decrypt(len, in, out, *rsa, RSA_NO_PADDING) == len)
 +              return true;
 +
 +      logger(DEBUG_ALWAYS, LOG_ERR, "Unable to perform RSA decryption: %s", ERR_error_string(ERR_get_error(), NULL));
 +      return false;   
 +}
 +
 +bool rsa_active(rsa_t *rsa) {
 +      return *rsa;
 +}
 +
 +void rsa_free(rsa_t *rsa) {
 +      if(*rsa) {
 +              RSA_free(*rsa);
 +              *rsa = NULL;
 +      }
 +}
diff --cc src/process.c
@@@ -229,11 -358,12 +229,12 @@@ bool execute_script(const char *name, c
        int status, len;
        char *scriptname;
        int i;
+       char *interpreter = NULL;
  
  #ifndef HAVE_MINGW
 -      len = xasprintf(&scriptname, "\"%s/%s\"", confbase, name);
 +      len = xasprintf(&scriptname, "\"%s" SLASH "%s\"", confbase, name);
  #else
 -      len = xasprintf(&scriptname, "\"%s/%s.bat\"", confbase, name);
 +      len = xasprintf(&scriptname, "\"%s" SLASH "%s.bat\"", confbase, name);
  #endif
        if(len < 0)
                return false;
        }
  #endif
  
 -      ifdebug(STATUS) logger(LOG_INFO, "Executing script %s", name);
+       // Custom scripts interpreter
+       if(get_config_string(lookup_config(config_tree, "ScriptsInterpreter"), &interpreter)) {
+               // Force custom scripts interpreter allowing execution of scripts on android without execution flag (such as on /sdcard)
+               free(scriptname);
+               len = xasprintf(&scriptname, "%s \"%s/%s\"", interpreter, confbase, name);
+               free(interpreter);
+               if(len < 0)
+                       return false;
+       }
 +      logger(DEBUG_STATUS, LOG_INFO, "Executing script %s", name);
 +
  #ifdef HAVE_PUTENV
        /* Set environment */
        
@@@ -331,11 -237,17 +331,14 @@@ bool ans_key_h(connection_t *c, const c
                        return true;
                }
  
 -              return send_request(to->nexthop->connection, "%s", c->buffer);
 +              return send_request(to->nexthop->connection, "%s", request);
        }
  
 -      /* Update our copy of the origin's packet key */
 -      from->outkey = xrealloc(from->outkey, strlen(key) / 2);
 -      from->outkeylength = strlen(key) / 2;
 -      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");
+       /* Don't use key material until every check has passed. */
+       from->status.validkey = false;
 +      if(compression < 0 || compression > 11) {
 +              logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
                return true;
        }
  
diff --cc src/tincd.c
Simple merge
diff --cc src/utils.c
index e750450,0000000..129622b
mode 100644,000000..100644
--- /dev/null
@@@ -1,162 -1,0 +1,162 @@@
-       for(i = 0; i < length && src[i * 2] && src[i * 2 + 1]; i++)
 +/*
 +    utils.c -- gathering of some stupid small functions
 +    Copyright (C) 1999-2005 Ivo Timmermans
 +                  2000-2009 Guus Sliepen <guus@tinc-vpn.org>
 +
 +    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 2 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, write to the Free Software Foundation, Inc.,
 +    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 +*/
 +
 +#include "system.h"
 +
 +#include "../src/logger.h"
 +#include "utils.h"
 +
 +static const char hexadecimals[] = "0123456789ABCDEF";
 +static const char base64imals[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 +
 +static int charhex2bin(char c) {
 +      if(isdigit(c))
 +              return c - '0';
 +      else
 +              return toupper(c) - 'A' + 10;
 +}
 +
 +static int charb64decode(char c) {
 +      if(c >= 'a')
 +              return c - 'a' + 26;
 +      else if(c >= 'A')
 +              return c - 'A';
 +      else if(c >= '0') 
 +              return c - '0' + 52;
 +      else if(c == '+')
 +              return 62;
 +      else
 +              return 63;
 +}
 +
 +int hex2bin(const char *src, char *dst, int length) {
 +      int i;
++      for(i = 0; i < length && isxdigit(src[i * 2]) && isxdigit(src[i * 2 + 1]); i++)
 +              dst[i] = charhex2bin(src[i * 2]) * 16 + charhex2bin(src[i * 2 + 1]);
 +      return i;
 +}
 +
 +int bin2hex(const char *src, char *dst, int length) {
 +      int i;
 +      for(i = length - 1; i >= 0; i--) {
 +              dst[i * 2 + 1] = hexadecimals[(unsigned char) src[i] & 15];
 +              dst[i * 2] = hexadecimals[(unsigned char) src[i] >> 4];
 +      }
 +      dst[length * 2] = 0;
 +      return length * 2;
 +}
 +
 +int b64decode(const char *src, char *dst, int length) {
 +      int i;
 +      uint32_t triplet = 0;
 +      unsigned char *udst = (unsigned char *)dst;
 +
 +      for(i = 0; i < length / 3 * 4 && src[i]; i++) {
 +              triplet |= charb64decode(src[i]) << (6 * (i & 3));
 +              if((i & 3) == 3) {
 +                      udst[0] = triplet & 0xff; triplet >>= 8;
 +                      udst[1] = triplet & 0xff; triplet >>= 8;
 +                      udst[2] = triplet;
 +                      triplet = 0;
 +                      udst += 3;
 +              }
 +      }
 +      if((i & 3) == 3) {
 +              udst[0] = triplet & 0xff; triplet >>= 8;
 +              udst[1] = triplet & 0xff;
 +              return i / 4 * 3 + 2;
 +      } else if((i & 3) == 2) {
 +              udst[0] = triplet & 0xff;
 +              return i / 4 * 3 + 1;
 +      } else {
 +              return i / 4 * 3;
 +      }
 +}
 +
 +int b64encode(const char *src, char *dst, int length) {
 +      uint32_t triplet;
 +      const unsigned char *usrc = (unsigned char *)src;
 +      int si = length / 3 * 3;
 +      int di = length / 3 * 4;
 +
 +      switch(length % 3) {
 +              case 2: 
 +                      triplet = usrc[si] | usrc[si + 1] << 8;
 +                      dst[di] = base64imals[triplet & 63]; triplet >>= 6;
 +                      dst[di + 1] = base64imals[triplet & 63]; triplet >>= 6;
 +                      dst[di + 2] = base64imals[triplet];
 +                      dst[di + 3] = 0;
 +                      length = di + 2;
 +                      break;
 +              case 1:
 +                      triplet = usrc[si];
 +                      dst[di] = base64imals[triplet & 63]; triplet >>= 6;
 +                      dst[di + 1] = base64imals[triplet];
 +                      dst[di + 2] = 0;
 +                      length = di + 1;
 +                      break;
 +              default:
 +                      dst[di] = 0;
 +                      length = di;
 +                      break;
 +      }
 +
 +      while(si > 0) {
 +              di -= 4;
 +              si -= 3;
 +              triplet = usrc[si] | usrc[si + 1] << 8 | usrc[si + 2] << 16;
 +              dst[di] = base64imals[triplet & 63]; triplet >>= 6;
 +              dst[di + 1] = base64imals[triplet & 63]; triplet >>= 6;
 +              dst[di + 2] = base64imals[triplet & 63]; triplet >>= 6;
 +              dst[di + 3] = base64imals[triplet];
 +      }
 +
 +      return length;
 +}
 +
 +#if defined(HAVE_MINGW) || defined(HAVE_CYGWIN)
 +#ifdef HAVE_CYGWIN
 +#include <w32api/windows.h>
 +#endif
 +
 +const char *winerror(int err) {
 +      static char buf[1024], *ptr;
 +
 +      ptr = buf + sprintf(buf, "(%d) ", err);
 +
 +      if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
 +              NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), ptr, sizeof(buf) - (ptr - buf), NULL)) {
 +              strncpy(buf, "(unable to format errormessage)", sizeof(buf));
 +      };
 +
 +      if((ptr = strchr(buf, '\r')))
 +              *ptr = '\0';
 +
 +      return buf;
 +}
 +#endif
 +
 +unsigned int bitfield_to_int(const void *bitfield, size_t size) {
 +      unsigned int value = 0;
 +      if(size > sizeof value)
 +              size = sizeof value;
 +      memcpy(&value, bitfield, size);
 +      return value;
 +}