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");
--- /dev/null
- 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;
+ }
+}
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 */
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;
}
--- /dev/null
- 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;
+}